Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "BenchTimer.h" | 8 #include "BenchTimer.h" |
| 9 #include "ResultsWriter.h" | |
| 9 #include "SkBenchLogger.h" | 10 #include "SkBenchLogger.h" |
| 10 #include "SkBenchmark.h" | 11 #include "SkBenchmark.h" |
| 11 #include "SkBitmapDevice.h" | 12 #include "SkBitmapDevice.h" |
| 12 #include "SkCanvas.h" | 13 #include "SkCanvas.h" |
| 13 #include "SkColorPriv.h" | 14 #include "SkColorPriv.h" |
| 14 #include "SkCommandLineFlags.h" | 15 #include "SkCommandLineFlags.h" |
| 15 #include "SkDeferredCanvas.h" | 16 #include "SkDeferredCanvas.h" |
| 16 #include "SkGraphics.h" | 17 #include "SkGraphics.h" |
| 17 #include "SkImageEncoder.h" | 18 #include "SkImageEncoder.h" |
| 18 #include "SkOSFile.h" | 19 #include "SkOSFile.h" |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 AutoPrePostDraw(SkBenchmark* bench) : fBench(bench) { | 77 AutoPrePostDraw(SkBenchmark* bench) : fBench(bench) { |
| 77 fBench->preDraw(); | 78 fBench->preDraw(); |
| 78 } | 79 } |
| 79 ~AutoPrePostDraw() { | 80 ~AutoPrePostDraw() { |
| 80 fBench->postDraw(); | 81 fBench->postDraw(); |
| 81 } | 82 } |
| 82 private: | 83 private: |
| 83 SkBenchmark* fBench; | 84 SkBenchmark* fBench; |
| 84 }; | 85 }; |
| 85 | 86 |
| 87 // Calls the end() method of T on destruction. | |
| 88 template <typename T> class CallEnd : SkNoncopyable { | |
| 89 public: | |
| 90 CallEnd(T& obj) : fObj(obj) {} | |
| 91 ~CallEnd() { fObj.end(); } | |
| 92 private: | |
| 93 T& fObj; | |
| 94 }; | |
| 95 | |
| 86 static void make_filename(const char name[], SkString* path) { | 96 static void make_filename(const char name[], SkString* path) { |
| 87 path->set(name); | 97 path->set(name); |
| 88 for (int i = 0; name[i]; i++) { | 98 for (int i = 0; name[i]; i++) { |
| 89 switch (name[i]) { | 99 switch (name[i]) { |
| 90 case '/': | 100 case '/': |
| 91 case '\\': | 101 case '\\': |
| 92 case ' ': | 102 case ' ': |
| 93 case ':': | 103 case ':': |
| 94 path->writable_str()[i] = '-'; | 104 path->writable_str()[i] = '-'; |
| 95 break; | 105 break; |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 DEFINE_string(config, kDefaultsConfigStr, | 278 DEFINE_string(config, kDefaultsConfigStr, |
| 269 "Run configs given. By default, runs the configs marked \"runByDe fault\" in gConfigs."); | 279 "Run configs given. By default, runs the configs marked \"runByDe fault\" in gConfigs."); |
| 270 DEFINE_string(logFile, "", "Also write stdout here."); | 280 DEFINE_string(logFile, "", "Also write stdout here."); |
| 271 DEFINE_int32(minMs, 20, "Shortest time we'll allow a benchmark to run."); | 281 DEFINE_int32(minMs, 20, "Shortest time we'll allow a benchmark to run."); |
| 272 DEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run."); | 282 DEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run."); |
| 273 DEFINE_double(error, 0.01, | 283 DEFINE_double(error, 0.01, |
| 274 "Ratio of subsequent bench measurements must drop within 1±error t o converge."); | 284 "Ratio of subsequent bench measurements must drop within 1±error t o converge."); |
| 275 DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops."); | 285 DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops."); |
| 276 DEFINE_bool2(verbose, v, false, "Print more."); | 286 DEFINE_bool2(verbose, v, false, "Print more."); |
| 277 DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); | 287 DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); |
| 288 DEFINE_string(outResultsFile, "", "If given, the results will be written to the file in JSON format."); | |
| 278 | 289 |
| 279 // Has this bench converged? First arguments are milliseconds / loop iteration, | 290 // Has this bench converged? First arguments are milliseconds / loop iteration, |
| 280 // last is overall runtime in milliseconds. | 291 // last is overall runtime in milliseconds. |
| 281 static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw) { | 292 static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw) { |
| 282 if (currRaw < FLAGS_minMs) { | 293 if (currRaw < FLAGS_minMs) { |
| 283 return false; | 294 return false; |
| 284 } | 295 } |
| 285 const double low = 1 - FLAGS_error, high = 1 + FLAGS_error; | 296 const double low = 1 - FLAGS_error, high = 1 + FLAGS_error; |
| 286 const double ratio = currPerLoop / prevPerLoop; | 297 const double ratio = currPerLoop / prevPerLoop; |
| 287 return low < ratio && ratio < high; | 298 return low < ratio && ratio < high; |
| 288 } | 299 } |
| 289 | 300 |
| 290 int tool_main(int argc, char** argv); | 301 int tool_main(int argc, char** argv); |
| 291 int tool_main(int argc, char** argv) { | 302 int tool_main(int argc, char** argv) { |
| 292 #if SK_ENABLE_INST_COUNT | 303 #if SK_ENABLE_INST_COUNT |
| 293 gPrintInstCount = true; | 304 gPrintInstCount = true; |
| 294 #endif | 305 #endif |
| 295 SkAutoGraphics ag; | 306 SkAutoGraphics ag; |
| 296 SkCommandLineFlags::Parse(argc, argv); | 307 SkCommandLineFlags::Parse(argc, argv); |
| 297 | 308 |
| 298 // First, parse some flags. | 309 // First, parse some flags. |
| 299 | |
| 300 SkBenchLogger logger; | 310 SkBenchLogger logger; |
| 301 if (FLAGS_logFile.count()) { | 311 if (FLAGS_logFile.count()) { |
| 302 logger.SetLogFile(FLAGS_logFile[0]); | 312 logger.SetLogFile(FLAGS_logFile[0]); |
| 303 } | 313 } |
| 304 | 314 |
| 315 LoggerResultsWriter logWriter(logger, FLAGS_timeFormat[0]); | |
| 316 MultiResultsWriter writer; | |
| 317 writer.add(&logWriter); | |
| 318 SkAutoTDelete<JSONResultsWriter> jsonWriter; | |
| 319 if (FLAGS_outResultsFile.count()) { | |
| 320 jsonWriter.reset(SkNEW(JSONResultsWriter(FLAGS_outResultsFile[0]))); | |
| 321 writer.add(jsonWriter.get()); | |
| 322 } | |
| 323 // Instantiate after all the writers have been added to writer so that we | |
| 324 // call close() before their destructors are called on the way out. | |
| 325 CallEnd<MultiResultsWriter> ender(writer); | |
| 326 | |
| 305 const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF; | 327 const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF; |
| 306 SkTriState::State dither = SkTriState::kDefault; | 328 SkTriState::State dither = SkTriState::kDefault; |
| 307 for (size_t i = 0; i < 3; i++) { | 329 for (size_t i = 0; i < 3; i++) { |
| 308 if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) { | 330 if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) { |
| 309 dither = static_cast<SkTriState::State>(i); | 331 dither = static_cast<SkTriState::State>(i); |
| 310 } | 332 } |
| 311 } | 333 } |
| 312 | 334 |
| 313 BenchMode benchMode = kNormal_BenchMode; | 335 BenchMode benchMode = kNormal_BenchMode; |
| 314 for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) { | 336 for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 } | 399 } |
| 378 } | 400 } |
| 379 } | 401 } |
| 380 #endif | 402 #endif |
| 381 | 403 |
| 382 // All flags should be parsed now. Report our settings. | 404 // All flags should be parsed now. Report our settings. |
| 383 if (kIsDebug) { | 405 if (kIsDebug) { |
| 384 logger.logError("bench was built in Debug mode, so we're going to hide t he times." | 406 logger.logError("bench was built in Debug mode, so we're going to hide t he times." |
| 385 " It's for your own good!\n"); | 407 " It's for your own good!\n"); |
| 386 } | 408 } |
| 387 SkString str("skia bench:"); | 409 writer.option("mode", FLAGS_mode[0]); |
| 388 str.appendf(" mode=%s", FLAGS_mode[0]); | 410 writer.option("alpha", SkStringPrintf("0x%02X", alpha).c_str()); |
| 389 str.appendf(" alpha=0x%02X antialias=%d filter=%d dither=%s", | 411 writer.option("antialias", SkStringPrintf("%d", FLAGS_forceAA).c_str()); |
| 390 alpha, FLAGS_forceAA, FLAGS_forceFilter, SkTriState::Name[dither ]); | 412 writer.option("filter", SkStringPrintf("%d", FLAGS_forceFilter).c_str()); |
| 391 str.appendf(" rotate=%d scale=%d clip=%d", FLAGS_rotate, FLAGS_scale, FLAGS_ clip); | 413 writer.option("dither", SkTriState::Name[dither]); |
| 414 | |
| 415 writer.option("rotate", SkStringPrintf("%d", FLAGS_rotate).c_str()); | |
| 416 writer.option("scale", SkStringPrintf("%d", FLAGS_scale).c_str()); | |
| 417 writer.option("clip", SkStringPrintf("%d", FLAGS_clip).c_str()); | |
| 392 | 418 |
| 393 #if defined(SK_SCALAR_IS_FIXED) | 419 #if defined(SK_SCALAR_IS_FIXED) |
| 394 str.append(" scalar=fixed"); | 420 writer.option("scalar", "fixed"); |
| 395 #else | 421 #else |
| 396 str.append(" scalar=float"); | 422 writer.option("scalar", "float"); |
| 397 #endif | 423 #endif |
| 398 | 424 |
| 399 #if defined(SK_BUILD_FOR_WIN32) | 425 #if defined(SK_BUILD_FOR_WIN32) |
| 400 str.append(" system=WIN32"); | 426 writer.option("system", "WIN32"); |
| 401 #elif defined(SK_BUILD_FOR_MAC) | 427 #elif defined(SK_BUILD_FOR_MAC) |
| 402 str.append(" system=MAC"); | 428 writer.option("system", "MAC"); |
| 403 #elif defined(SK_BUILD_FOR_ANDROID) | 429 #elif defined(SK_BUILD_FOR_ANDROID) |
| 404 str.append(" system=ANDROID"); | 430 writer.option("system", "ANDROID"); |
| 405 #elif defined(SK_BUILD_FOR_UNIX) | 431 #elif defined(SK_BUILD_FOR_UNIX) |
| 406 str.append(" system=UNIX"); | 432 writer.option("system", "UNIX"); |
| 407 #else | 433 #else |
| 408 str.append(" system=other"); | 434 writer.option("system", "other"); |
| 409 #endif | 435 #endif |
| 410 | 436 |
| 411 #if defined(SK_DEBUG) | 437 #if defined(SK_DEBUG) |
| 412 str.append(" DEBUG"); | 438 writer.option("build", "DEBUG"); |
| 439 #else | |
| 440 writer.option("build", "RELEASE"); | |
| 413 #endif | 441 #endif |
| 414 str.append("\n"); | |
| 415 logger.logProgress(str); | |
| 416 | |
| 417 | 442 |
| 418 // Set texture cache limits if non-default. | 443 // Set texture cache limits if non-default. |
| 419 for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) { | 444 for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) { |
| 420 #if SK_SUPPORT_GPU | 445 #if SK_SUPPORT_GPU |
| 421 const Config& config = gConfigs[i]; | 446 const Config& config = gConfigs[i]; |
| 422 if (SkBenchmark::kGPU_Backend != config.backend) { | 447 if (SkBenchmark::kGPU_Backend != config.backend) { |
| 423 continue; | 448 continue; |
| 424 } | 449 } |
| 425 GrContext* context = gContextFactory.get(config.contextType); | 450 GrContext* context = gContextFactory.get(config.contextType); |
| 426 if (NULL == context) { | 451 if (NULL == context) { |
| 427 continue; | 452 continue; |
| 428 } | 453 } |
| 429 | 454 |
| 430 size_t bytes; | 455 size_t bytes; |
| 431 int count; | 456 int count; |
| 432 context->getTextureCacheLimits(&count, &bytes); | 457 context->getTextureCacheLimits(&count, &bytes); |
| 433 if (-1 != FLAGS_gpuCacheBytes) { | 458 if (-1 != FLAGS_gpuCacheBytes) { |
| 434 bytes = static_cast<size_t>(FLAGS_gpuCacheBytes); | 459 bytes = static_cast<size_t>(FLAGS_gpuCacheBytes); |
| 435 } | 460 } |
| 436 if (-1 != FLAGS_gpuCacheCount) { | 461 if (-1 != FLAGS_gpuCacheCount) { |
| 437 count = FLAGS_gpuCacheCount; | 462 count = FLAGS_gpuCacheCount; |
| 438 } | 463 } |
| 439 context->setTextureCacheLimits(count, bytes); | 464 context->setTextureCacheLimits(count, bytes); |
| 440 #endif | 465 #endif |
| 441 } | 466 } |
| 442 | 467 |
| 443 // Find the longest name of the benches we're going to run to make the outpu t pretty. | |
| 444 Iter names; | |
| 445 SkBenchmark* bench; | |
| 446 size_t longestName = 0; | |
| 447 while ((bench = names.next()) != NULL) { | |
| 448 SkAutoTUnref<SkBenchmark> benchUnref(bench); | |
| 449 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { | |
| 450 continue; | |
| 451 } | |
| 452 const size_t length = strlen(bench->getName()); | |
| 453 longestName = length > longestName ? length : longestName; | |
| 454 } | |
| 455 | |
| 456 // Run each bench in each configuration it supports and we asked for. | 468 // Run each bench in each configuration it supports and we asked for. |
| 457 Iter iter; | 469 Iter iter; |
| 470 SkBenchmark* bench; | |
| 458 while ((bench = iter.next()) != NULL) { | 471 while ((bench = iter.next()) != NULL) { |
| 459 SkAutoTUnref<SkBenchmark> benchUnref(bench); | 472 SkAutoTUnref<SkBenchmark> benchUnref(bench); |
| 460 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { | 473 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { |
| 461 continue; | 474 continue; |
| 462 } | 475 } |
| 463 | 476 |
| 464 bench->setForceAlpha(alpha); | 477 bench->setForceAlpha(alpha); |
| 465 bench->setForceAA(FLAGS_forceAA); | 478 bench->setForceAA(FLAGS_forceAA); |
| 466 bench->setForceFilter(FLAGS_forceFilter); | 479 bench->setForceFilter(FLAGS_forceFilter); |
| 467 bench->setDither(dither); | 480 bench->setDither(dither); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 530 | 543 |
| 531 if (NULL != canvas) { | 544 if (NULL != canvas) { |
| 532 canvas->clear(SK_ColorWHITE); | 545 canvas->clear(SK_ColorWHITE); |
| 533 if (FLAGS_clip) { performClip(canvas, dim.fX, dim.fY); } | 546 if (FLAGS_clip) { performClip(canvas, dim.fX, dim.fY); } |
| 534 if (FLAGS_scale) { performScale(canvas, dim.fX, dim.fY); } | 547 if (FLAGS_scale) { performScale(canvas, dim.fX, dim.fY); } |
| 535 if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); } | 548 if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); } |
| 536 } | 549 } |
| 537 | 550 |
| 538 if (!loggedBenchName) { | 551 if (!loggedBenchName) { |
| 539 loggedBenchName = true; | 552 loggedBenchName = true; |
| 540 SkString str; | 553 writer.bench(bench->getName(), dim.fX, dim.fY); |
| 541 str.printf("running bench [%3d %3d] %*s ", | |
| 542 dim.fX, dim.fY, (int)longestName, bench->getName()); | |
| 543 logger.logProgress(str); | |
| 544 } | 554 } |
| 545 | 555 |
| 546 #if SK_SUPPORT_GPU | 556 #if SK_SUPPORT_GPU |
| 547 SkGLContextHelper* contextHelper = NULL; | 557 SkGLContextHelper* contextHelper = NULL; |
| 548 if (SkBenchmark::kGPU_Backend == config.backend) { | 558 if (SkBenchmark::kGPU_Backend == config.backend) { |
| 549 contextHelper = gContextFactory.getGLContext(config.contextType) ; | 559 contextHelper = gContextFactory.getGLContext(config.contextType) ; |
| 550 } | 560 } |
| 551 BenchTimer timer(contextHelper); | 561 BenchTimer timer(contextHelper); |
| 552 #else | 562 #else |
| 553 BenchTimer timer; | 563 BenchTimer timer; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 672 // Normalize to ms per 1000 iterations. | 682 // Normalize to ms per 1000 iterations. |
| 673 const double normalize = 1000.0 / loopsPerIter; | 683 const double normalize = 1000.0 / loopsPerIter; |
| 674 const struct { char shortName; const char* longName; double ms; } ti mes[] = { | 684 const struct { char shortName; const char* longName; double ms; } ti mes[] = { |
| 675 {'w', "msecs", normalize * timer.fWall}, | 685 {'w', "msecs", normalize * timer.fWall}, |
| 676 {'W', "Wmsecs", normalize * timer.fTruncatedWall}, | 686 {'W', "Wmsecs", normalize * timer.fTruncatedWall}, |
| 677 {'c', "cmsecs", normalize * timer.fCpu}, | 687 {'c', "cmsecs", normalize * timer.fCpu}, |
| 678 {'C', "Cmsecs", normalize * timer.fTruncatedCpu}, | 688 {'C', "Cmsecs", normalize * timer.fTruncatedCpu}, |
| 679 {'g', "gmsecs", normalize * timer.fGpu}, | 689 {'g', "gmsecs", normalize * timer.fGpu}, |
| 680 }; | 690 }; |
| 681 | 691 |
| 682 SkString result; | 692 writer.config(config.name); |
| 683 result.appendf(" %s:", config.name); | |
| 684 for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) { | 693 for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) { |
| 685 if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) { | 694 if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) { |
| 686 result.appendf(" %s = ", times[i].longName); | 695 writer.timer(times[i].longName, times[i].ms); |
| 687 result.appendf(FLAGS_timeFormat[0], times[i].ms); | |
| 688 } | 696 } |
| 689 } | 697 } |
| 690 logger.logProgress(result); | |
| 691 } | |
| 692 if (loggedBenchName) { | |
| 693 logger.logProgress("\n"); | |
| 694 } | 698 } |
| 695 } | 699 } |
| 700 writer.end(); | |
|
djsollen
2013/11/25 20:29:28
don't need this anymore.
jcgregorio
2013/11/25 20:57:42
Done.
| |
| 696 #if SK_SUPPORT_GPU | 701 #if SK_SUPPORT_GPU |
| 697 gContextFactory.destroyContexts(); | 702 gContextFactory.destroyContexts(); |
| 698 #endif | 703 #endif |
| 699 return 0; | 704 return 0; |
| 700 } | 705 } |
| 701 | 706 |
| 702 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 707 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
| 703 int main(int argc, char * const argv[]) { | 708 int main(int argc, char * const argv[]) { |
| 704 return tool_main(argc, (char**) argv); | 709 return tool_main(argc, (char**) argv); |
| 705 } | 710 } |
| 706 #endif | 711 #endif |
| OLD | NEW |