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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 DEFINE_string(config, kDefaultsConfigStr, | 269 DEFINE_string(config, kDefaultsConfigStr, |
269 "Run configs given. By default, runs the configs marked \"runByDe
fault\" in gConfigs."); | 270 "Run configs given. By default, runs the configs marked \"runByDe
fault\" in gConfigs."); |
270 DEFINE_string(logFile, "", "Also write stdout here."); | 271 DEFINE_string(logFile, "", "Also write stdout here."); |
271 DEFINE_int32(minMs, 20, "Shortest time we'll allow a benchmark to run."); | 272 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."); | 273 DEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run."); |
273 DEFINE_double(error, 0.01, | 274 DEFINE_double(error, 0.01, |
274 "Ratio of subsequent bench measurements must drop within 1±error t
o converge."); | 275 "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."); | 276 DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per
1000 loops."); |
276 DEFINE_bool2(verbose, v, false, "Print more."); | 277 DEFINE_bool2(verbose, v, false, "Print more."); |
277 DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); | 278 DEFINE_string2(resourcePath, i, NULL, "directory for test resources."); |
| 279 DEFINE_string(outResultsFile, "", "If given, the results will be written to the
file in JSON format."); |
278 | 280 |
279 // Has this bench converged? First arguments are milliseconds / loop iteration, | 281 // Has this bench converged? First arguments are milliseconds / loop iteration, |
280 // last is overall runtime in milliseconds. | 282 // last is overall runtime in milliseconds. |
281 static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw)
{ | 283 static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw)
{ |
282 if (currRaw < FLAGS_minMs) { | 284 if (currRaw < FLAGS_minMs) { |
283 return false; | 285 return false; |
284 } | 286 } |
285 const double low = 1 - FLAGS_error, high = 1 + FLAGS_error; | 287 const double low = 1 - FLAGS_error, high = 1 + FLAGS_error; |
286 const double ratio = currPerLoop / prevPerLoop; | 288 const double ratio = currPerLoop / prevPerLoop; |
287 return low < ratio && ratio < high; | 289 return low < ratio && ratio < high; |
288 } | 290 } |
289 | 291 |
290 int tool_main(int argc, char** argv); | 292 int tool_main(int argc, char** argv); |
291 int tool_main(int argc, char** argv) { | 293 int tool_main(int argc, char** argv) { |
292 #if SK_ENABLE_INST_COUNT | 294 #if SK_ENABLE_INST_COUNT |
293 gPrintInstCount = true; | 295 gPrintInstCount = true; |
294 #endif | 296 #endif |
295 SkAutoGraphics ag; | 297 SkAutoGraphics ag; |
296 SkCommandLineFlags::Parse(argc, argv); | 298 SkCommandLineFlags::Parse(argc, argv); |
297 | 299 |
298 // First, parse some flags. | 300 // First, parse some flags. |
299 | |
300 SkBenchLogger logger; | 301 SkBenchLogger logger; |
301 if (FLAGS_logFile.count()) { | 302 if (FLAGS_logFile.count()) { |
302 logger.SetLogFile(FLAGS_logFile[0]); | 303 logger.SetLogFile(FLAGS_logFile[0]); |
303 } | 304 } |
304 | 305 |
| 306 LoggerResultsWriter logWriter(logger, FLAGS_timeFormat[0]); |
| 307 MultiResultsWriter writer; |
| 308 writer.add(&logWriter); |
| 309 SkAutoTDelete<JSONResultsWriter> jsonWriter; |
| 310 if (FLAGS_outResultsFile.count()) { |
| 311 jsonWriter.reset(SkNEW(JSONResultsWriter(FLAGS_outResultsFile[0]))); |
| 312 writer.add(jsonWriter.get()); |
| 313 } |
| 314 // Instantiate after all the writers have been added to writer so that we |
| 315 // call close() before their destructors are called on the way out. |
| 316 CallEnd<MultiResultsWriter> ender(writer); |
| 317 |
305 const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF; | 318 const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF; |
306 SkTriState::State dither = SkTriState::kDefault; | 319 SkTriState::State dither = SkTriState::kDefault; |
307 for (size_t i = 0; i < 3; i++) { | 320 for (size_t i = 0; i < 3; i++) { |
308 if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) { | 321 if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) { |
309 dither = static_cast<SkTriState::State>(i); | 322 dither = static_cast<SkTriState::State>(i); |
310 } | 323 } |
311 } | 324 } |
312 | 325 |
313 BenchMode benchMode = kNormal_BenchMode; | 326 BenchMode benchMode = kNormal_BenchMode; |
314 for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) { | 327 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 } | 390 } |
378 } | 391 } |
379 } | 392 } |
380 #endif | 393 #endif |
381 | 394 |
382 // All flags should be parsed now. Report our settings. | 395 // All flags should be parsed now. Report our settings. |
383 if (kIsDebug) { | 396 if (kIsDebug) { |
384 logger.logError("bench was built in Debug mode, so we're going to hide t
he times." | 397 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"); | 398 " It's for your own good!\n"); |
386 } | 399 } |
387 SkString str("skia bench:"); | 400 writer.option("mode", FLAGS_mode[0]); |
388 str.appendf(" mode=%s", FLAGS_mode[0]); | 401 writer.option("alpha", SkStringPrintf("0x%02X", alpha).c_str()); |
389 str.appendf(" alpha=0x%02X antialias=%d filter=%d dither=%s", | 402 writer.option("antialias", SkStringPrintf("%d", FLAGS_forceAA).c_str()); |
390 alpha, FLAGS_forceAA, FLAGS_forceFilter, SkTriState::Name[dither
]); | 403 writer.option("filter", SkStringPrintf("%d", FLAGS_forceFilter).c_str()); |
391 str.appendf(" rotate=%d scale=%d clip=%d", FLAGS_rotate, FLAGS_scale, FLAGS_
clip); | 404 writer.option("dither", SkTriState::Name[dither]); |
| 405 |
| 406 writer.option("rotate", SkStringPrintf("%d", FLAGS_rotate).c_str()); |
| 407 writer.option("scale", SkStringPrintf("%d", FLAGS_scale).c_str()); |
| 408 writer.option("clip", SkStringPrintf("%d", FLAGS_clip).c_str()); |
392 | 409 |
393 #if defined(SK_SCALAR_IS_FIXED) | 410 #if defined(SK_SCALAR_IS_FIXED) |
394 str.append(" scalar=fixed"); | 411 writer.option("scalar", "fixed"); |
395 #else | 412 #else |
396 str.append(" scalar=float"); | 413 writer.option("scalar", "float"); |
397 #endif | 414 #endif |
398 | 415 |
399 #if defined(SK_BUILD_FOR_WIN32) | 416 #if defined(SK_BUILD_FOR_WIN32) |
400 str.append(" system=WIN32"); | 417 writer.option("system", "WIN32"); |
401 #elif defined(SK_BUILD_FOR_MAC) | 418 #elif defined(SK_BUILD_FOR_MAC) |
402 str.append(" system=MAC"); | 419 writer.option("system", "MAC"); |
403 #elif defined(SK_BUILD_FOR_ANDROID) | 420 #elif defined(SK_BUILD_FOR_ANDROID) |
404 str.append(" system=ANDROID"); | 421 writer.option("system", "ANDROID"); |
405 #elif defined(SK_BUILD_FOR_UNIX) | 422 #elif defined(SK_BUILD_FOR_UNIX) |
406 str.append(" system=UNIX"); | 423 writer.option("system", "UNIX"); |
407 #else | 424 #else |
408 str.append(" system=other"); | 425 writer.option("system", "other"); |
409 #endif | 426 #endif |
410 | 427 |
411 #if defined(SK_DEBUG) | 428 #if defined(SK_DEBUG) |
412 str.append(" DEBUG"); | 429 writer.option("build", "DEBUG"); |
| 430 #else |
| 431 writer.option("build", "RELEASE"); |
413 #endif | 432 #endif |
414 str.append("\n"); | |
415 logger.logProgress(str); | |
416 | |
417 | 433 |
418 // Set texture cache limits if non-default. | 434 // Set texture cache limits if non-default. |
419 for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) { | 435 for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) { |
420 #if SK_SUPPORT_GPU | 436 #if SK_SUPPORT_GPU |
421 const Config& config = gConfigs[i]; | 437 const Config& config = gConfigs[i]; |
422 if (SkBenchmark::kGPU_Backend != config.backend) { | 438 if (SkBenchmark::kGPU_Backend != config.backend) { |
423 continue; | 439 continue; |
424 } | 440 } |
425 GrContext* context = gContextFactory.get(config.contextType); | 441 GrContext* context = gContextFactory.get(config.contextType); |
426 if (NULL == context) { | 442 if (NULL == context) { |
427 continue; | 443 continue; |
428 } | 444 } |
429 | 445 |
430 size_t bytes; | 446 size_t bytes; |
431 int count; | 447 int count; |
432 context->getTextureCacheLimits(&count, &bytes); | 448 context->getTextureCacheLimits(&count, &bytes); |
433 if (-1 != FLAGS_gpuCacheBytes) { | 449 if (-1 != FLAGS_gpuCacheBytes) { |
434 bytes = static_cast<size_t>(FLAGS_gpuCacheBytes); | 450 bytes = static_cast<size_t>(FLAGS_gpuCacheBytes); |
435 } | 451 } |
436 if (-1 != FLAGS_gpuCacheCount) { | 452 if (-1 != FLAGS_gpuCacheCount) { |
437 count = FLAGS_gpuCacheCount; | 453 count = FLAGS_gpuCacheCount; |
438 } | 454 } |
439 context->setTextureCacheLimits(count, bytes); | 455 context->setTextureCacheLimits(count, bytes); |
440 #endif | 456 #endif |
441 } | 457 } |
442 | 458 |
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. | 459 // Run each bench in each configuration it supports and we asked for. |
457 Iter iter; | 460 Iter iter; |
| 461 SkBenchmark* bench; |
458 while ((bench = iter.next()) != NULL) { | 462 while ((bench = iter.next()) != NULL) { |
459 SkAutoTUnref<SkBenchmark> benchUnref(bench); | 463 SkAutoTUnref<SkBenchmark> benchUnref(bench); |
460 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { | 464 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { |
461 continue; | 465 continue; |
462 } | 466 } |
463 | 467 |
464 bench->setForceAlpha(alpha); | 468 bench->setForceAlpha(alpha); |
465 bench->setForceAA(FLAGS_forceAA); | 469 bench->setForceAA(FLAGS_forceAA); |
466 bench->setForceFilter(FLAGS_forceFilter); | 470 bench->setForceFilter(FLAGS_forceFilter); |
467 bench->setDither(dither); | 471 bench->setDither(dither); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 | 534 |
531 if (NULL != canvas) { | 535 if (NULL != canvas) { |
532 canvas->clear(SK_ColorWHITE); | 536 canvas->clear(SK_ColorWHITE); |
533 if (FLAGS_clip) { performClip(canvas, dim.fX, dim.fY); } | 537 if (FLAGS_clip) { performClip(canvas, dim.fX, dim.fY); } |
534 if (FLAGS_scale) { performScale(canvas, dim.fX, dim.fY); } | 538 if (FLAGS_scale) { performScale(canvas, dim.fX, dim.fY); } |
535 if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); } | 539 if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); } |
536 } | 540 } |
537 | 541 |
538 if (!loggedBenchName) { | 542 if (!loggedBenchName) { |
539 loggedBenchName = true; | 543 loggedBenchName = true; |
540 SkString str; | 544 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 } | 545 } |
545 | 546 |
546 #if SK_SUPPORT_GPU | 547 #if SK_SUPPORT_GPU |
547 SkGLContextHelper* contextHelper = NULL; | 548 SkGLContextHelper* contextHelper = NULL; |
548 if (SkBenchmark::kGPU_Backend == config.backend) { | 549 if (SkBenchmark::kGPU_Backend == config.backend) { |
549 contextHelper = gContextFactory.getGLContext(config.contextType)
; | 550 contextHelper = gContextFactory.getGLContext(config.contextType)
; |
550 } | 551 } |
551 BenchTimer timer(contextHelper); | 552 BenchTimer timer(contextHelper); |
552 #else | 553 #else |
553 BenchTimer timer; | 554 BenchTimer timer; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 // Normalize to ms per 1000 iterations. | 673 // Normalize to ms per 1000 iterations. |
673 const double normalize = 1000.0 / loopsPerIter; | 674 const double normalize = 1000.0 / loopsPerIter; |
674 const struct { char shortName; const char* longName; double ms; } ti
mes[] = { | 675 const struct { char shortName; const char* longName; double ms; } ti
mes[] = { |
675 {'w', "msecs", normalize * timer.fWall}, | 676 {'w', "msecs", normalize * timer.fWall}, |
676 {'W', "Wmsecs", normalize * timer.fTruncatedWall}, | 677 {'W', "Wmsecs", normalize * timer.fTruncatedWall}, |
677 {'c', "cmsecs", normalize * timer.fCpu}, | 678 {'c', "cmsecs", normalize * timer.fCpu}, |
678 {'C', "Cmsecs", normalize * timer.fTruncatedCpu}, | 679 {'C', "Cmsecs", normalize * timer.fTruncatedCpu}, |
679 {'g', "gmsecs", normalize * timer.fGpu}, | 680 {'g', "gmsecs", normalize * timer.fGpu}, |
680 }; | 681 }; |
681 | 682 |
682 SkString result; | 683 writer.config(config.name); |
683 result.appendf(" %s:", config.name); | |
684 for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) { | 684 for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) { |
685 if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms >
0) { | 685 if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms >
0) { |
686 result.appendf(" %s = ", times[i].longName); | 686 writer.timer(times[i].longName, times[i].ms); |
687 result.appendf(FLAGS_timeFormat[0], times[i].ms); | |
688 } | 687 } |
689 } | 688 } |
690 logger.logProgress(result); | |
691 } | |
692 if (loggedBenchName) { | |
693 logger.logProgress("\n"); | |
694 } | 689 } |
695 } | 690 } |
696 #if SK_SUPPORT_GPU | 691 #if SK_SUPPORT_GPU |
697 gContextFactory.destroyContexts(); | 692 gContextFactory.destroyContexts(); |
698 #endif | 693 #endif |
699 return 0; | 694 return 0; |
700 } | 695 } |
701 | 696 |
702 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 697 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
703 int main(int argc, char * const argv[]) { | 698 int main(int argc, char * const argv[]) { |
704 return tool_main(argc, (char**) argv); | 699 return tool_main(argc, (char**) argv); |
705 } | 700 } |
706 #endif | 701 #endif |
OLD | NEW |