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 |