Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: bench/benchmain.cpp

Issue 197873010: --dryRun flag for bench (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "ResultsWriter.h"
10 #include "SkBenchLogger.h" 10 #include "SkBenchLogger.h"
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 DEFINE_string(logFile, "", "Also write stdout here."); 260 DEFINE_string(logFile, "", "Also write stdout here.");
261 DEFINE_int32(minMs, 20, "Shortest time we'll allow a benchmark to run."); 261 DEFINE_int32(minMs, 20, "Shortest time we'll allow a benchmark to run.");
262 DEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run."); 262 DEFINE_int32(maxMs, 4000, "Longest time we'll allow a benchmark to run.");
263 DEFINE_double(error, 0.01, 263 DEFINE_double(error, 0.01,
264 "Ratio of subsequent bench measurements must drop within 1±error t o converge."); 264 "Ratio of subsequent bench measurements must drop within 1±error t o converge.");
265 DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops."); 265 DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops.");
266 DEFINE_bool2(verbose, v, false, "Print more."); 266 DEFINE_bool2(verbose, v, false, "Print more.");
267 DEFINE_string2(resourcePath, i, "resources", "directory for test resources."); 267 DEFINE_string2(resourcePath, i, "resources", "directory for test resources.");
268 DEFINE_string(outResultsFile, "", "If given, the results will be written to the file in JSON format."); 268 DEFINE_string(outResultsFile, "", "If given, the results will be written to the file in JSON format.");
269 269
270 DEFINE_bool(dryRun, false, "Don't actually run the tests, just print what would have been done.");
271
270 // Has this bench converged? First arguments are milliseconds / loop iteration, 272 // Has this bench converged? First arguments are milliseconds / loop iteration,
271 // last is overall runtime in milliseconds. 273 // last is overall runtime in milliseconds.
272 static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw) { 274 static bool HasConverged(double prevPerLoop, double currPerLoop, double currRaw) {
273 if (currRaw < FLAGS_minMs) { 275 if (currRaw < FLAGS_minMs) {
274 return false; 276 return false;
275 } 277 }
276 const double low = 1 - FLAGS_error, high = 1 + FLAGS_error; 278 const double low = 1 - FLAGS_error, high = 1 + FLAGS_error;
277 const double ratio = currPerLoop / prevPerLoop; 279 const double ratio = currPerLoop / prevPerLoop;
278 return low < ratio && ratio < high; 280 return low < ratio && ratio < high;
279 } 281 }
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 bool converged = false; 546 bool converged = false;
545 547
546 // variables used to compute loopsPerFrame 548 // variables used to compute loopsPerFrame
547 double frameIntervalTime = 0.0f; 549 double frameIntervalTime = 0.0f;
548 int frameIntervalTotalLoops = 0; 550 int frameIntervalTotalLoops = 0;
549 551
550 bool frameIntervalComputed = false; 552 bool frameIntervalComputed = false;
551 int loopsPerFrame = 0; 553 int loopsPerFrame = 0;
552 int loopsPerIter = 0; 554 int loopsPerIter = 0;
553 if (FLAGS_verbose) { SkDebugf("%s %s: ", bench->getName(), config.na me); } 555 if (FLAGS_verbose) { SkDebugf("%s %s: ", bench->getName(), config.na me); }
554 do { 556 if (!FLAGS_dryRun) {
555 // Ramp up 1 -> 2 -> 4 -> 8 -> 16 -> ... -> ~1 billion. 557 do {
556 loopsPerIter = (loopsPerIter == 0) ? 1 : loopsPerIter * 2; 558 // Ramp up 1 -> 2 -> 4 -> 8 -> 16 -> ... -> ~1 billion.
557 if (loopsPerIter >= (1<<30) || timer.fWall > FLAGS_maxMs) { 559 loopsPerIter = (loopsPerIter == 0) ? 1 : loopsPerIter * 2;
558 // If you find it takes more than a billion loops to get up to 20ms of runtime, 560 if (loopsPerIter >= (1<<30) || timer.fWall > FLAGS_maxMs) {
559 // you've got a computer clocked at several THz or have a br oken benchmark. ;) 561 // If you find it takes more than a billion loops to get up to 20ms of runtime,
560 // "1B ought to be enough for anybody." 562 // you've got a computer clocked at several THz or have a broken benchmark. ;)
561 logger.logError(SkStringPrintf( 563 // "1B ought to be enough for anybody."
562 "\nCan't get %s %s to converge in %dms (%d loops)", 564 logger.logError(SkStringPrintf(
563 bench->getName(), config.name, FLAGS_maxMs, loopsPerIte r)); 565 "\nCan't get %s %s to converge in %dms (%d loops)",
564 break; 566 bench->getName(), config.name, FLAGS_maxMs, loopsPe rIter));
565 } 567 break;
566
567 if ((benchMode == kRecord_BenchMode || benchMode == kPictureReco rd_BenchMode)) {
568 // Clear the recorded commands so that they do not accumulat e.
569 canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, k RecordFlags)));
570 }
571
572 timer.start();
573 // Inner loop that allows us to break the run into smaller
574 // chunks (e.g. frames). This is especially useful for the GPU
575 // as we can flush and/or swap buffers to keep the GPU from
576 // queuing up too much work.
577 for (int loopCount = loopsPerIter; loopCount > 0; ) {
578 // Save and restore around each call to draw() to guarantee a pristine canvas.
579 SkAutoCanvasRestore saveRestore(canvas, true/*also save*/);
580
581 int loops;
582 if (frameIntervalComputed && loopCount > loopsPerFrame) {
583 loops = loopsPerFrame;
584 loopCount -= loopsPerFrame;
585 } else {
586 loops = loopCount;
587 loopCount = 0;
588 } 568 }
589 569
590 if (benchMode == kPictureRecord_BenchMode) { 570 if ((benchMode == kRecord_BenchMode || benchMode == kPicture Record_BenchMode)) {
591 recordFrom.draw(canvas); 571 // Clear the recorded commands so that they do not accum ulate.
592 } else { 572 canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.f Y, kRecordFlags)));
593 bench->draw(loops, canvas);
594 } 573 }
595 574
596 if (kDeferredSilent_BenchMode == benchMode) { 575 timer.start();
597 static_cast<SkDeferredCanvas*>(canvas.get())->silentFlus h(); 576 // Inner loop that allows us to break the run into smaller
598 } else if (NULL != canvas) { 577 // chunks (e.g. frames). This is especially useful for the G PU
599 canvas->flush(); 578 // as we can flush and/or swap buffers to keep the GPU from
579 // queuing up too much work.
580 for (int loopCount = loopsPerIter; loopCount > 0; ) {
581 // Save and restore around each call to draw() to guaran tee a pristine canvas.
582 SkAutoCanvasRestore saveRestore(canvas, true/*also save* /);
583
584 int loops;
585 if (frameIntervalComputed && loopCount > loopsPerFrame) {
586 loops = loopsPerFrame;
587 loopCount -= loopsPerFrame;
588 } else {
589 loops = loopCount;
590 loopCount = 0;
591 }
592
593 if (benchMode == kPictureRecord_BenchMode) {
594 recordFrom.draw(canvas);
595 } else {
596 bench->draw(loops, canvas);
597 }
598
599 if (kDeferredSilent_BenchMode == benchMode) {
600 static_cast<SkDeferredCanvas*>(canvas.get())->silent Flush();
601 } else if (NULL != canvas) {
602 canvas->flush();
603 }
604
605 #if SK_SUPPORT_GPU
606 // swap drawing buffers on each frame to prevent the GPU
607 // from queuing up too much work
608 if (NULL != glContext) {
609 glContext->swapBuffers();
610 }
611 #endif
600 } 612 }
601 613
602 #if SK_SUPPORT_GPU
603 // swap drawing buffers on each frame to prevent the GPU
604 // from queuing up too much work
605 if (NULL != glContext) {
606 glContext->swapBuffers();
607 }
608 #endif
609 }
610
611 614
612 615
613 // Stop truncated timers before GL calls complete, and stop the full timers after. 616 // Stop truncated timers before GL calls complete, and stop the full timers after.
614 timer.truncatedEnd(); 617 timer.truncatedEnd();
615 #if SK_SUPPORT_GPU 618 #if SK_SUPPORT_GPU
616 if (NULL != glContext) { 619 if (NULL != glContext) {
617 context->flush(); 620 context->flush();
618 SK_GL(*glContext, Finish()); 621 SK_GL(*glContext, Finish());
619 } 622 }
620 #endif 623 #endif
621 timer.end(); 624 timer.end();
622 625
623 // setup the frame interval for subsequent iterations 626 // setup the frame interval for subsequent iterations
624 if (!frameIntervalComputed) { 627 if (!frameIntervalComputed) {
625 frameIntervalTime += timer.fWall; 628 frameIntervalTime += timer.fWall;
626 frameIntervalTotalLoops += loopsPerIter; 629 frameIntervalTotalLoops += loopsPerIter;
627 if (frameIntervalTime >= FLAGS_minMs) { 630 if (frameIntervalTime >= FLAGS_minMs) {
628 frameIntervalComputed = true; 631 frameIntervalComputed = true;
629 loopsPerFrame = 632 loopsPerFrame =
630 (int)(((double)frameIntervalTotalLoops / frameInterval Time) * FLAGS_minMs); 633 (int)(((double)frameIntervalTotalLoops / frameInte rvalTime) * FLAGS_minMs);
631 if (loopsPerFrame < 1) { 634 if (loopsPerFrame < 1) {
632 loopsPerFrame = 1; 635 loopsPerFrame = 1;
636 }
637 // SkDebugf(" %s has %d loops in %f ms (normalized t o %d)\n",
638 // bench->getName(), frameIntervalTotalLoops ,
639 // timer.fWall, loopsPerFrame);
633 } 640 }
634 // SkDebugf(" %s has %d loops in %f ms (normalized to %d )\n",
635 // bench->getName(), frameIntervalTotalLoops,
636 // timer.fWall, loopsPerFrame);
637 } 641 }
638 }
639 642
640 const double current = timer.fWall / loopsPerIter; 643 const double current = timer.fWall / loopsPerIter;
641 if (FLAGS_verbose && current > previous) { SkDebugf("↑"); } 644 if (FLAGS_verbose && current > previous) { SkDebugf("↑"); }
642 if (FLAGS_verbose) { SkDebugf("%.3g ", current); } 645 if (FLAGS_verbose) { SkDebugf("%.3g ", current); }
643 converged = HasConverged(previous, current, timer.fWall); 646 converged = HasConverged(previous, current, timer.fWall);
644 previous = current; 647 previous = current;
645 } while (!kIsDebug && !converged); 648 } while (!kIsDebug && !converged);
649 }
646 if (FLAGS_verbose) { SkDebugf("\n"); } 650 if (FLAGS_verbose) { SkDebugf("\n"); }
647 651
648 if (FLAGS_outDir.count() && SkBenchmark::kNonRendering_Backend != co nfig.backend) { 652 if (!FLAGS_dryRun && FLAGS_outDir.count() && SkBenchmark::kNonRender ing_Backend != config.backend) {
649 SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); 653 SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
650 if (image.get()) { 654 if (image.get()) {
651 saveFile(bench->getName(), config.name, FLAGS_outDir[0], 655 saveFile(bench->getName(), config.name, FLAGS_outDir[0],
652 image); 656 image);
653 } 657 }
654 } 658 }
655 659
656 if (kIsDebug) { 660 if (kIsDebug) {
657 // Let's not mislead ourselves by looking at Debug build bench t imes! 661 // Let's not mislead ourselves by looking at Debug build bench t imes!
658 continue; 662 continue;
(...skipping 21 matching lines...) Expand all
680 gContextFactory.destroyContexts(); 684 gContextFactory.destroyContexts();
681 #endif 685 #endif
682 return 0; 686 return 0;
683 } 687 }
684 688
685 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 689 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
686 int main(int argc, char * const argv[]) { 690 int main(int argc, char * const argv[]) {
687 return tool_main(argc, (char**) argv); 691 return tool_main(argc, (char**) argv);
688 } 692 }
689 #endif 693 #endif
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698