OLD | NEW |
1 #include "SkBenchmark.h" | 1 #include "SkBenchmark.h" |
2 #include "SkColorPriv.h" | 2 #include "SkColorPriv.h" |
3 #include "SkMatrix.h" | 3 #include "SkMatrix.h" |
4 #include "SkRandom.h" | 4 #include "SkRandom.h" |
5 #include "SkString.h" | 5 #include "SkString.h" |
6 #include "SkPaint.h" | 6 #include "SkPaint.h" |
7 | 7 |
8 static float sk_fsel(float pred, float result_ge, float result_lt) { | 8 static float sk_fsel(float pred, float result_ge, float result_lt) { |
9 return pred >= 0 ? result_ge : result_lt; | 9 return pred >= 0 ? result_ge : result_lt; |
10 } | 10 } |
11 | 11 |
12 static float fast_floor(float x) { | 12 static float fast_floor(float x) { |
13 // float big = sk_fsel(x, 0x1.0p+23, -0x1.0p+23); | 13 // float big = sk_fsel(x, 0x1.0p+23, -0x1.0p+23); |
14 float big = sk_fsel(x, (float)(1 << 23), -(float)(1 << 23)); | 14 float big = sk_fsel(x, (float)(1 << 23), -(float)(1 << 23)); |
15 return (x + big) - big; | 15 return (x + big) - big; |
16 } | 16 } |
17 | 17 |
18 class MathBench : public SkBenchmark { | 18 class MathBench : public SkBenchmark { |
19 enum { | 19 enum { |
20 kBuffer = 100, | 20 kBuffer = 100, |
21 kLoop = 10000 | |
22 }; | 21 }; |
23 SkString fName; | 22 SkString fName; |
24 float fSrc[kBuffer], fDst[kBuffer]; | 23 float fSrc[kBuffer], fDst[kBuffer]; |
25 public: | 24 public: |
26 MathBench(void* param, const char name[]) : INHERITED(param) { | 25 MathBench(void* param, const char name[]) : INHERITED(param) { |
27 fName.printf("math_%s", name); | 26 fName.printf("math_%s", name); |
28 | 27 |
29 SkRandom rand; | 28 SkRandom rand; |
30 for (int i = 0; i < kBuffer; ++i) { | 29 for (int i = 0; i < kBuffer; ++i) { |
31 fSrc[i] = rand.nextSScalar1(); | 30 fSrc[i] = rand.nextSScalar1(); |
32 } | 31 } |
33 | 32 |
34 fIsRendering = false; | 33 fIsRendering = false; |
35 } | 34 } |
36 | 35 |
37 virtual void performTest(float* SK_RESTRICT dst, | 36 virtual void performTest(float* SK_RESTRICT dst, |
38 const float* SK_RESTRICT src, | 37 const float* SK_RESTRICT src, |
39 int count) = 0; | 38 int count) = 0; |
40 | 39 |
41 protected: | 40 protected: |
42 virtual int mulLoopCount() const { return 1; } | 41 virtual int mulLoopCount() const { return 1; } |
43 | 42 |
44 virtual const char* onGetName() { | 43 virtual const char* onGetName() { |
45 return fName.c_str(); | 44 return fName.c_str(); |
46 } | 45 } |
47 | 46 |
48 virtual void onDraw(SkCanvas*) { | 47 virtual void onDraw(SkCanvas*) { |
49 int n = SkBENCHLOOP(kLoop * this->mulLoopCount()); | 48 int n = this->getLoops() * this->mulLoopCount(); |
50 for (int i = 0; i < n; i++) { | 49 for (int i = 0; i < n; i++) { |
51 this->performTest(fDst, fSrc, kBuffer); | 50 this->performTest(fDst, fSrc, kBuffer); |
52 } | 51 } |
53 } | 52 } |
54 | 53 |
55 private: | 54 private: |
56 typedef SkBenchmark INHERITED; | 55 typedef SkBenchmark INHERITED; |
57 }; | 56 }; |
58 | 57 |
59 class MathBenchU32 : public MathBench { | 58 class MathBenchU32 : public MathBench { |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 // a + b will be NaN iff either a or b is NaN. | 239 // a + b will be NaN iff either a or b is NaN. |
241 float value = r.fLeft * 0 + r.fTop * 0 + r.fRight * 0 + r.fBottom * 0; | 240 float value = r.fLeft * 0 + r.fTop * 0 + r.fRight * 0 + r.fBottom * 0; |
242 | 241 |
243 // value is either NaN or it is finite (zero). | 242 // value is either NaN or it is finite (zero). |
244 // value==value will be true iff value is not NaN | 243 // value==value will be true iff value is not NaN |
245 return value == value; | 244 return value == value; |
246 } | 245 } |
247 | 246 |
248 class IsFiniteBench : public SkBenchmark { | 247 class IsFiniteBench : public SkBenchmark { |
249 enum { | 248 enum { |
250 N = SkBENCHLOOP(1000), | 249 N = 1000, |
251 NN = SkBENCHLOOP(1000), | |
252 }; | 250 }; |
253 float fData[N]; | 251 float fData[N]; |
254 public: | 252 public: |
255 | 253 |
256 IsFiniteBench(void* param, int index) : INHERITED(param) { | 254 IsFiniteBench(void* param, int index) : INHERITED(param) { |
257 SkRandom rand; | 255 SkRandom rand; |
258 | 256 |
259 for (int i = 0; i < N; ++i) { | 257 for (int i = 0; i < N; ++i) { |
260 fData[i] = rand.nextSScalar1(); | 258 fData[i] = rand.nextSScalar1(); |
261 } | 259 } |
262 | 260 |
263 if (index < 0) { | 261 if (index < 0) { |
264 fProc = NULL; | 262 fProc = NULL; |
265 fName = "isfinite_rect"; | 263 fName = "isfinite_rect"; |
266 } else { | 264 } else { |
267 fProc = gRec[index].fProc; | 265 fProc = gRec[index].fProc; |
268 fName = gRec[index].fName; | 266 fName = gRec[index].fName; |
269 } | 267 } |
270 fIsRendering = false; | 268 fIsRendering = false; |
271 } | 269 } |
272 | 270 |
273 protected: | 271 protected: |
274 virtual void onDraw(SkCanvas*) { | 272 virtual void onDraw(SkCanvas*) { |
275 IsFiniteProc proc = fProc; | 273 IsFiniteProc proc = fProc; |
276 const float* data = fData; | 274 const float* data = fData; |
277 // do this so the compiler won't throw away the function call | 275 // do this so the compiler won't throw away the function call |
278 int counter = 0; | 276 int counter = 0; |
279 | 277 |
280 if (proc) { | 278 if (proc) { |
281 for (int j = 0; j < NN; ++j) { | 279 for (int j = 0; j < this->getLoops(); ++j) { |
282 for (int i = 0; i < N - 4; ++i) { | 280 for (int i = 0; i < N - 4; ++i) { |
283 counter += proc(&data[i]); | 281 counter += proc(&data[i]); |
284 } | 282 } |
285 } | 283 } |
286 } else { | 284 } else { |
287 for (int j = 0; j < NN; ++j) { | 285 for (int j = 0; j < this->getLoops(); ++j) { |
288 for (int i = 0; i < N - 4; ++i) { | 286 for (int i = 0; i < N - 4; ++i) { |
289 const SkRect* r = reinterpret_cast<const SkRect*>(&data[i]); | 287 const SkRect* r = reinterpret_cast<const SkRect*>(&data[i]); |
290 if (false) { // avoid bit rot, suppress warning | 288 if (false) { // avoid bit rot, suppress warning |
291 isFinite(*r); | 289 isFinite(*r); |
292 } | 290 } |
293 counter += r->isFinite(); | 291 counter += r->isFinite(); |
294 } | 292 } |
295 } | 293 } |
296 } | 294 } |
297 | 295 |
298 SkPaint paint; | 296 SkPaint paint; |
299 if (paint.getAlpha() == 0) { | 297 if (paint.getAlpha() == 0) { |
300 SkDebugf("%d\n", counter); | 298 SkDebugf("%d\n", counter); |
301 } | 299 } |
302 } | 300 } |
303 | 301 |
304 virtual const char* onGetName() { | 302 virtual const char* onGetName() { |
305 return fName; | 303 return fName; |
306 } | 304 } |
307 | 305 |
308 private: | 306 private: |
309 IsFiniteProc fProc; | 307 IsFiniteProc fProc; |
310 const char* fName; | 308 const char* fName; |
311 | 309 |
312 typedef SkBenchmark INHERITED; | 310 typedef SkBenchmark INHERITED; |
313 }; | 311 }; |
314 | 312 |
315 class FloorBench : public SkBenchmark { | 313 class FloorBench : public SkBenchmark { |
316 enum { | 314 enum { |
317 ARRAY = SkBENCHLOOP(1000), | 315 ARRAY = 1000, |
318 LOOP = SkBENCHLOOP(1000), | |
319 }; | 316 }; |
320 float fData[ARRAY]; | 317 float fData[ARRAY]; |
321 bool fFast; | 318 bool fFast; |
322 public: | 319 public: |
323 | 320 |
324 FloorBench(void* param, bool fast) : INHERITED(param), fFast(fast) { | 321 FloorBench(void* param, bool fast) : INHERITED(param), fFast(fast) { |
325 SkRandom rand; | 322 SkRandom rand; |
326 | 323 |
327 for (int i = 0; i < ARRAY; ++i) { | 324 for (int i = 0; i < ARRAY; ++i) { |
328 fData[i] = rand.nextSScalar1(); | 325 fData[i] = rand.nextSScalar1(); |
329 } | 326 } |
330 | 327 |
331 if (fast) { | 328 if (fast) { |
332 fName = "floor_fast"; | 329 fName = "floor_fast"; |
333 } else { | 330 } else { |
334 fName = "floor_std"; | 331 fName = "floor_std"; |
335 } | 332 } |
336 fIsRendering = false; | 333 fIsRendering = false; |
337 } | 334 } |
338 | 335 |
339 virtual void process(float) {} | 336 virtual void process(float) {} |
340 | 337 |
341 protected: | 338 protected: |
342 virtual void onDraw(SkCanvas*) { | 339 virtual void onDraw(SkCanvas*) { |
343 SkRandom rand; | 340 SkRandom rand; |
344 float accum = 0; | 341 float accum = 0; |
345 const float* data = fData; | 342 const float* data = fData; |
346 | 343 |
347 if (fFast) { | 344 if (fFast) { |
348 for (int j = 0; j < LOOP; ++j) { | 345 for (int j = 0; j < this->getLoops(); ++j) { |
349 for (int i = 0; i < ARRAY; ++i) { | 346 for (int i = 0; i < ARRAY; ++i) { |
350 accum += fast_floor(data[i]); | 347 accum += fast_floor(data[i]); |
351 } | 348 } |
352 this->process(accum); | 349 this->process(accum); |
353 } | 350 } |
354 } else { | 351 } else { |
355 for (int j = 0; j < LOOP; ++j) { | 352 for (int j = 0; j < this->getLoops(); ++j) { |
356 for (int i = 0; i < ARRAY; ++i) { | 353 for (int i = 0; i < ARRAY; ++i) { |
357 accum += sk_float_floor(data[i]); | 354 accum += sk_float_floor(data[i]); |
358 } | 355 } |
359 this->process(accum); | 356 this->process(accum); |
360 } | 357 } |
361 } | 358 } |
362 } | 359 } |
363 | 360 |
364 virtual const char* onGetName() { | 361 virtual const char* onGetName() { |
365 return fName; | 362 return fName; |
366 } | 363 } |
367 | 364 |
368 private: | 365 private: |
369 const char* fName; | 366 const char* fName; |
370 | 367 |
371 typedef SkBenchmark INHERITED; | 368 typedef SkBenchmark INHERITED; |
372 }; | 369 }; |
373 | 370 |
374 class CLZBench : public SkBenchmark { | 371 class CLZBench : public SkBenchmark { |
375 enum { | 372 enum { |
376 ARRAY = SkBENCHLOOP(1000), | 373 ARRAY = 1000, |
377 LOOP = SkBENCHLOOP(5000), | |
378 }; | 374 }; |
379 uint32_t fData[ARRAY]; | 375 uint32_t fData[ARRAY]; |
380 bool fUsePortable; | 376 bool fUsePortable; |
381 | 377 |
382 public: | 378 public: |
383 CLZBench(void* param, bool usePortable) | 379 CLZBench(void* param, bool usePortable) |
384 : INHERITED(param) | 380 : INHERITED(param) |
385 , fUsePortable(usePortable) { | 381 , fUsePortable(usePortable) { |
386 | 382 |
387 SkRandom rand; | 383 SkRandom rand; |
(...skipping 10 matching lines...) Expand all Loading... |
398 } | 394 } |
399 | 395 |
400 // just so the compiler doesn't remove our loops | 396 // just so the compiler doesn't remove our loops |
401 virtual void process(int) {} | 397 virtual void process(int) {} |
402 | 398 |
403 protected: | 399 protected: |
404 virtual void onDraw(SkCanvas*) { | 400 virtual void onDraw(SkCanvas*) { |
405 int accum = 0; | 401 int accum = 0; |
406 | 402 |
407 if (fUsePortable) { | 403 if (fUsePortable) { |
408 for (int j = 0; j < LOOP; ++j) { | 404 for (int j = 0; j < this->getLoops(); ++j) { |
409 for (int i = 0; i < ARRAY; ++i) { | 405 for (int i = 0; i < ARRAY; ++i) { |
410 accum += SkCLZ_portable(fData[i]); | 406 accum += SkCLZ_portable(fData[i]); |
411 } | 407 } |
412 this->process(accum); | 408 this->process(accum); |
413 } | 409 } |
414 } else { | 410 } else { |
415 for (int j = 0; j < LOOP; ++j) { | 411 for (int j = 0; j < this->getLoops(); ++j) { |
416 for (int i = 0; i < ARRAY; ++i) { | 412 for (int i = 0; i < ARRAY; ++i) { |
417 accum += SkCLZ(fData[i]); | 413 accum += SkCLZ(fData[i]); |
418 } | 414 } |
419 this->process(accum); | 415 this->process(accum); |
420 } | 416 } |
421 } | 417 } |
422 } | 418 } |
423 | 419 |
424 virtual const char* onGetName() { | 420 virtual const char* onGetName() { |
425 return fName; | 421 return fName; |
426 } | 422 } |
427 | 423 |
428 private: | 424 private: |
429 const char* fName; | 425 const char* fName; |
430 | 426 |
431 typedef SkBenchmark INHERITED; | 427 typedef SkBenchmark INHERITED; |
432 }; | 428 }; |
433 | 429 |
434 /////////////////////////////////////////////////////////////////////////////// | 430 /////////////////////////////////////////////////////////////////////////////// |
435 | 431 |
436 class NormalizeBench : public SkBenchmark { | 432 class NormalizeBench : public SkBenchmark { |
437 enum { | 433 enum { |
438 ARRAY = SkBENCHLOOP(1000), | 434 ARRAY =1000, |
439 LOOP = SkBENCHLOOP(1000), | |
440 }; | 435 }; |
441 SkVector fVec[ARRAY]; | 436 SkVector fVec[ARRAY]; |
442 | 437 |
443 public: | 438 public: |
444 NormalizeBench(void* param) | 439 NormalizeBench(void* param) |
445 : INHERITED(param) { | 440 : INHERITED(param) { |
446 | 441 |
447 SkRandom rand; | 442 SkRandom rand; |
448 for (int i = 0; i < ARRAY; ++i) { | 443 for (int i = 0; i < ARRAY; ++i) { |
449 fVec[i].set(rand.nextSScalar1(), rand.nextSScalar1()); | 444 fVec[i].set(rand.nextSScalar1(), rand.nextSScalar1()); |
450 } | 445 } |
451 | 446 |
452 fName = "point_normalize"; | 447 fName = "point_normalize"; |
453 fIsRendering = false; | 448 fIsRendering = false; |
454 } | 449 } |
455 | 450 |
456 // just so the compiler doesn't remove our loops | 451 // just so the compiler doesn't remove our loops |
457 virtual void process(int) {} | 452 virtual void process(int) {} |
458 | 453 |
459 protected: | 454 protected: |
460 virtual void onDraw(SkCanvas*) { | 455 virtual void onDraw(SkCanvas*) { |
461 int accum = 0; | 456 int accum = 0; |
462 | 457 |
463 for (int j = 0; j < LOOP; ++j) { | 458 for (int j = 0; j < this->getLoops(); ++j) { |
464 for (int i = 0; i < ARRAY; ++i) { | 459 for (int i = 0; i < ARRAY; ++i) { |
465 accum += fVec[i].normalize(); | 460 accum += fVec[i].normalize(); |
466 } | 461 } |
467 this->process(accum); | 462 this->process(accum); |
468 } | 463 } |
469 } | 464 } |
470 | 465 |
471 virtual const char* onGetName() { | 466 virtual const char* onGetName() { |
472 return fName; | 467 return fName; |
473 } | 468 } |
474 | 469 |
475 private: | 470 private: |
476 const char* fName; | 471 const char* fName; |
477 | 472 |
478 typedef SkBenchmark INHERITED; | 473 typedef SkBenchmark INHERITED; |
479 }; | 474 }; |
480 | 475 |
481 /////////////////////////////////////////////////////////////////////////////// | 476 /////////////////////////////////////////////////////////////////////////////// |
482 | 477 |
483 class FixedMathBench : public SkBenchmark { | 478 class FixedMathBench : public SkBenchmark { |
484 enum { | 479 enum { |
485 N = SkBENCHLOOP(1000), | 480 N = 1000, |
486 NN = SkBENCHLOOP(1000), | |
487 }; | 481 }; |
488 float fData[N]; | 482 float fData[N]; |
489 SkFixed fResult[N]; | 483 SkFixed fResult[N]; |
490 public: | 484 public: |
491 | 485 |
492 FixedMathBench(void* param) : INHERITED(param) { | 486 FixedMathBench(void* param) : INHERITED(param) { |
493 SkRandom rand; | 487 SkRandom rand; |
494 for (int i = 0; i < N; ++i) { | 488 for (int i = 0; i < this->getLoops(); ++i) { |
495 fData[i] = rand.nextSScalar1(); | 489 fData[i%N] = rand.nextSScalar1(); |
496 } | 490 } |
497 | 491 |
498 fIsRendering = false; | 492 fIsRendering = false; |
499 } | 493 } |
500 | 494 |
501 protected: | 495 protected: |
502 virtual void onDraw(SkCanvas*) { | 496 virtual void onDraw(SkCanvas*) { |
503 for (int j = 0; j < NN; ++j) { | 497 for (int j = 0; j < this->getLoops(); ++j) { |
504 for (int i = 0; i < N - 4; ++i) { | 498 for (int i = 0; i < N - 4; ++i) { |
505 fResult[i] = SkFloatToFixed(fData[i]); | 499 fResult[i] = SkFloatToFixed(fData[i]); |
506 } | 500 } |
507 } | 501 } |
508 | 502 |
509 SkPaint paint; | 503 SkPaint paint; |
510 if (paint.getAlpha() == 0) { | 504 if (paint.getAlpha() == 0) { |
511 SkDebugf("%d\n", fResult[0]); | 505 SkDebugf("%d\n", fResult[0]); |
512 } | 506 } |
513 } | 507 } |
(...skipping 24 matching lines...) Expand all Loading... |
538 | 532 |
539 DEF_BENCH( return new FloorBench(p, false); ) | 533 DEF_BENCH( return new FloorBench(p, false); ) |
540 DEF_BENCH( return new FloorBench(p, true); ) | 534 DEF_BENCH( return new FloorBench(p, true); ) |
541 | 535 |
542 DEF_BENCH( return new CLZBench(p, false); ) | 536 DEF_BENCH( return new CLZBench(p, false); ) |
543 DEF_BENCH( return new CLZBench(p, true); ) | 537 DEF_BENCH( return new CLZBench(p, true); ) |
544 | 538 |
545 DEF_BENCH( return new NormalizeBench(p); ) | 539 DEF_BENCH( return new NormalizeBench(p); ) |
546 | 540 |
547 DEF_BENCH( return new FixedMathBench(p); ) | 541 DEF_BENCH( return new FixedMathBench(p); ) |
OLD | NEW |