| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 <ctype.h> | 8 #include <ctype.h> |
| 9 | 9 |
| 10 #include "nanobench.h" | 10 #include "nanobench.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 | 85 |
| 86 DEFINE_string(outResultsFile, "", "If given, write results here as JSON."); | 86 DEFINE_string(outResultsFile, "", "If given, write results here as JSON."); |
| 87 DEFINE_int32(maxCalibrationAttempts, 3, | 87 DEFINE_int32(maxCalibrationAttempts, 3, |
| 88 "Try up to this many times to guess loops for a bench, or skip the
bench."); | 88 "Try up to this many times to guess loops for a bench, or skip the
bench."); |
| 89 DEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this."); | 89 DEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this."); |
| 90 DEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs."); | 90 DEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs."); |
| 91 DEFINE_string(scales, "1.0", "Space-separated scales for SKPs."); | 91 DEFINE_string(scales, "1.0", "Space-separated scales for SKPs."); |
| 92 DEFINE_string(zoom, "1.0,1", "Comma-separated scale,step zoom factors for SKPs."
); | 92 DEFINE_string(zoom, "1.0,1", "Comma-separated scale,step zoom factors for SKPs."
); |
| 93 DEFINE_bool(bbh, true, "Build a BBH for SKPs?"); | 93 DEFINE_bool(bbh, true, "Build a BBH for SKPs?"); |
| 94 DEFINE_bool(mpd, true, "Use MultiPictureDraw for the SKPs?"); | 94 DEFINE_bool(mpd, true, "Use MultiPictureDraw for the SKPs?"); |
| 95 DEFINE_bool(loopSKP, true, "Loop SKPs like we do for micro benches?"); |
| 95 DEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run."); | 96 DEFINE_int32(flushEvery, 10, "Flush --outResultsFile every Nth run."); |
| 96 DEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each test
."); | 97 DEFINE_bool(resetGpuContext, true, "Reset the GrContext before running each test
."); |
| 97 DEFINE_bool(gpuStats, false, "Print GPU stats after each gpu benchmark?"); | 98 DEFINE_bool(gpuStats, false, "Print GPU stats after each gpu benchmark?"); |
| 98 | 99 |
| 99 static SkString humanize(double ms) { | 100 static SkString humanize(double ms) { |
| 100 if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); | 101 if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); |
| 101 return HumanizeMs(ms); | 102 return HumanizeMs(ms); |
| 102 } | 103 } |
| 103 #define HUMANIZE(ms) humanize(ms).c_str() | 104 #define HUMANIZE(ms) humanize(ms).c_str() |
| 104 | 105 |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 return false; | 266 return false; |
| 266 } | 267 } |
| 267 return true; | 268 return true; |
| 268 } | 269 } |
| 269 | 270 |
| 270 static int kFailedLoops = -2; | 271 static int kFailedLoops = -2; |
| 271 static int cpu_bench(const double overhead, Target* target, Benchmark* bench, do
uble* samples) { | 272 static int cpu_bench(const double overhead, Target* target, Benchmark* bench, do
uble* samples) { |
| 272 // First figure out approximately how many loops of bench it takes to make o
verhead negligible. | 273 // First figure out approximately how many loops of bench it takes to make o
verhead negligible. |
| 273 double bench_plus_overhead = 0.0; | 274 double bench_plus_overhead = 0.0; |
| 274 int round = 0; | 275 int round = 0; |
| 275 if (kAutoTuneLoops == FLAGS_loops) { | 276 int loops = bench->calculateLoops(FLAGS_loops); |
| 277 if (kAutoTuneLoops == loops) { |
| 276 while (bench_plus_overhead < overhead) { | 278 while (bench_plus_overhead < overhead) { |
| 277 if (round++ == FLAGS_maxCalibrationAttempts) { | 279 if (round++ == FLAGS_maxCalibrationAttempts) { |
| 278 SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skip
ping.\n", | 280 SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skip
ping.\n", |
| 279 bench->getUniqueName(), HUMANIZE(bench_plus_overhead),
HUMANIZE(overhead)); | 281 bench->getUniqueName(), HUMANIZE(bench_plus_overhead),
HUMANIZE(overhead)); |
| 280 return kFailedLoops; | 282 return kFailedLoops; |
| 281 } | 283 } |
| 282 bench_plus_overhead = time(1, bench, target); | 284 bench_plus_overhead = time(1, bench, target); |
| 283 } | 285 } |
| 284 } | 286 } |
| 285 | 287 |
| 286 // Later we'll just start and stop the timer once but loop N times. | 288 // Later we'll just start and stop the timer once but loop N times. |
| 287 // We'll pick N to make timer overhead negligible: | 289 // We'll pick N to make timer overhead negligible: |
| 288 // | 290 // |
| 289 // overhead | 291 // overhead |
| 290 // ------------------------- < FLAGS_overheadGoal | 292 // ------------------------- < FLAGS_overheadGoal |
| 291 // overhead + N * Bench Time | 293 // overhead + N * Bench Time |
| 292 // | 294 // |
| 293 // where bench_plus_overhead ≈ overhead + Bench Time. | 295 // where bench_plus_overhead ≈ overhead + Bench Time. |
| 294 // | 296 // |
| 295 // Doing some math, we get: | 297 // Doing some math, we get: |
| 296 // | 298 // |
| 297 // (overhead / FLAGS_overheadGoal) - overhead | 299 // (overhead / FLAGS_overheadGoal) - overhead |
| 298 // ------------------------------------------ < N | 300 // ------------------------------------------ < N |
| 299 // bench_plus_overhead - overhead) | 301 // bench_plus_overhead - overhead) |
| 300 // | 302 // |
| 301 // Luckily, this also works well in practice. :) | 303 // Luckily, this also works well in practice. :) |
| 302 int loops = FLAGS_loops; | |
| 303 if (kAutoTuneLoops == loops) { | 304 if (kAutoTuneLoops == loops) { |
| 304 const double numer = overhead / FLAGS_overheadGoal - overhead; | 305 const double numer = overhead / FLAGS_overheadGoal - overhead; |
| 305 const double denom = bench_plus_overhead - overhead; | 306 const double denom = bench_plus_overhead - overhead; |
| 306 loops = (int)ceil(numer / denom); | 307 loops = (int)ceil(numer / denom); |
| 307 loops = clamp_loops(loops); | 308 loops = clamp_loops(loops); |
| 308 } else { | 309 } else { |
| 309 loops = detect_forever_loops(loops); | 310 loops = detect_forever_loops(loops); |
| 310 } | 311 } |
| 311 | 312 |
| 312 for (int i = 0; i < FLAGS_samples; i++) { | 313 for (int i = 0; i < FLAGS_samples; i++) { |
| 313 samples[i] = time(loops, bench, target) / loops; | 314 samples[i] = time(loops, bench, target) / loops; |
| 314 } | 315 } |
| 315 return loops; | 316 return loops; |
| 316 } | 317 } |
| 317 | 318 |
| 318 static int gpu_bench(Target* target, | 319 static int gpu_bench(Target* target, |
| 319 Benchmark* bench, | 320 Benchmark* bench, |
| 320 double* samples, | 321 double* samples, |
| 321 int maxGpuFrameLag) { | 322 int maxGpuFrameLag) { |
| 322 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. | 323 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. |
| 323 int loops = FLAGS_loops; | 324 int loops = bench->calculateLoops(FLAGS_loops); |
| 324 if (kAutoTuneLoops == loops) { | 325 if (kAutoTuneLoops == loops) { |
| 325 loops = 1; | 326 loops = 1; |
| 326 double elapsed = 0; | 327 double elapsed = 0; |
| 327 do { | 328 do { |
| 328 if (1<<30 == loops) { | 329 if (1<<30 == loops) { |
| 329 // We're about to wrap. Something's wrong with the bench. | 330 // We're about to wrap. Something's wrong with the bench. |
| 330 loops = 0; | 331 loops = 0; |
| 331 break; | 332 break; |
| 332 } | 333 } |
| 333 loops *= 2; | 334 loops *= 2; |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 pic->playback(recorder.beginRecording(pic->cullRect().wi
dth(), | 709 pic->playback(recorder.beginRecording(pic->cullRect().wi
dth(), |
| 709 pic->cullRect().he
ight(), | 710 pic->cullRect().he
ight(), |
| 710 &factory, | 711 &factory, |
| 711 fUseMPDs[fCurrentU
seMPD] ? kFlags : 0)); | 712 fUseMPDs[fCurrentU
seMPD] ? kFlags : 0)); |
| 712 pic.reset(recorder.endRecording()); | 713 pic.reset(recorder.endRecording()); |
| 713 } | 714 } |
| 714 SkString name = SkOSPath::Basename(path.c_str()); | 715 SkString name = SkOSPath::Basename(path.c_str()); |
| 715 fSourceType = "skp"; | 716 fSourceType = "skp"; |
| 716 fBenchType = "playback"; | 717 fBenchType = "playback"; |
| 717 return SkNEW_ARGS(SKPBench, | 718 return SkNEW_ARGS(SKPBench, |
| 718 (name.c_str(), pic.get(), fClip, | 719 (name.c_str(), pic.get(), fClip, fScales[f
CurrentScale], |
| 719 fScales[fCurrentScale], fUseMPDs[fCurrent
UseMPD++])); | 720 fUseMPDs[fCurrentUseMPD++], FLAGS_loopSKP
)); |
| 720 | 721 |
| 721 } | 722 } |
| 722 fCurrentUseMPD = 0; | 723 fCurrentUseMPD = 0; |
| 723 fCurrentSKP++; | 724 fCurrentSKP++; |
| 724 } | 725 } |
| 725 fCurrentSKP = 0; | 726 fCurrentSKP = 0; |
| 726 fCurrentScale++; | 727 fCurrentScale++; |
| 727 } | 728 } |
| 728 | 729 |
| 729 // Now loop over each skp again if we have an animation | 730 // Now loop over each skp again if we have an animation |
| 730 if (fZoomScale != 1.0f && fZoomSteps != 1) { | 731 if (fZoomScale != 1.0f && fZoomSteps != 1) { |
| 731 while (fCurrentAnimSKP < fSKPs.count()) { | 732 while (fCurrentAnimSKP < fSKPs.count()) { |
| 732 const SkString& path = fSKPs[fCurrentAnimSKP]; | 733 const SkString& path = fSKPs[fCurrentAnimSKP]; |
| 733 SkAutoTUnref<SkPicture> pic; | 734 SkAutoTUnref<SkPicture> pic; |
| 734 if (!ReadPicture(path.c_str(), &pic)) { | 735 if (!ReadPicture(path.c_str(), &pic)) { |
| 735 fCurrentAnimSKP++; | 736 fCurrentAnimSKP++; |
| 736 continue; | 737 continue; |
| 737 } | 738 } |
| 738 | 739 |
| 739 fCurrentAnimSKP++; | 740 fCurrentAnimSKP++; |
| 740 SkString name = SkOSPath::Basename(path.c_str()); | 741 SkString name = SkOSPath::Basename(path.c_str()); |
| 741 SkMatrix anim = SkMatrix::I(); | 742 SkMatrix anim = SkMatrix::I(); |
| 742 anim.setScale(fZoomScale, fZoomScale); | 743 anim.setScale(fZoomScale, fZoomScale); |
| 743 return SkNEW_ARGS(SKPAnimationBench, (name.c_str(), pic.get(), f
Clip, anim, | 744 return SkNEW_ARGS(SKPAnimationBench, (name.c_str(), pic.get(), f
Clip, anim, |
| 744 fZoomSteps)); | 745 fZoomSteps, FLAGS_loopSKP)); |
| 745 } | 746 } |
| 746 } | 747 } |
| 747 | 748 |
| 748 | 749 |
| 749 for (; fCurrentCodec < fImages.count(); fCurrentCodec++) { | 750 for (; fCurrentCodec < fImages.count(); fCurrentCodec++) { |
| 750 const SkString& path = fImages[fCurrentCodec]; | 751 const SkString& path = fImages[fCurrentCodec]; |
| 751 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); | 752 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); |
| 752 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); | 753 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); |
| 753 if (!codec) { | 754 if (!codec) { |
| 754 // Nothing to time. | 755 // Nothing to time. |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 | 1120 |
| 1120 return 0; | 1121 return 0; |
| 1121 } | 1122 } |
| 1122 | 1123 |
| 1123 #if !defined SK_BUILD_FOR_IOS | 1124 #if !defined SK_BUILD_FOR_IOS |
| 1124 int main(int argc, char** argv) { | 1125 int main(int argc, char** argv) { |
| 1125 SkCommandLineFlags::Parse(argc, argv); | 1126 SkCommandLineFlags::Parse(argc, argv); |
| 1126 return nanobench_main(); | 1127 return nanobench_main(); |
| 1127 } | 1128 } |
| 1128 #endif | 1129 #endif |
| OLD | NEW |