| 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 "Benchmark.h" | 10 #include "Benchmark.h" |
| 11 #include "CrashHandler.h" | 11 #include "CrashHandler.h" |
| 12 #include "ResultsWriter.h" | 12 #include "ResultsWriter.h" |
| 13 #include "Stats.h" | 13 #include "Stats.h" |
| 14 #include "Timer.h" | 14 #include "Timer.h" |
| 15 | 15 |
| 16 #include "SkCanvas.h" | 16 #include "SkCanvas.h" |
| 17 #include "SkCommandLineFlags.h" | 17 #include "SkCommandLineFlags.h" |
| 18 #include "SkForceLinking.h" | 18 #include "SkForceLinking.h" |
| 19 #include "SkGraphics.h" | 19 #include "SkGraphics.h" |
| 20 #include "SkString.h" | 20 #include "SkString.h" |
| 21 #include "SkSurface.h" | 21 #include "SkSurface.h" |
| 22 | 22 |
| 23 #if SK_SUPPORT_GPU | 23 #if SK_SUPPORT_GPU |
| 24 #include "GrContextFactory.h" | 24 #include "GrContextFactory.h" |
| 25 GrContextFactory gGrFactory; | 25 GrContextFactory gGrFactory; |
| 26 #endif | 26 #endif |
| 27 | 27 |
| 28 __SK_FORCE_IMAGE_DECODER_LINKING; | 28 __SK_FORCE_IMAGE_DECODER_LINKING; |
| 29 | 29 |
| 30 #if SK_DEBUG |
| 31 DEFINE_bool(runOnce, true, "Run each benchmark just once?"); |
| 32 #else |
| 33 DEFINE_bool(runOnce, false, "Run each benchmark just once?"); |
| 34 #endif |
| 35 |
| 30 DEFINE_int32(samples, 10, "Number of samples to measure for each bench."); | 36 DEFINE_int32(samples, 10, "Number of samples to measure for each bench."); |
| 31 DEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead."); | 37 DEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead."); |
| 32 DEFINE_double(overheadGoal, 0.0001, | 38 DEFINE_double(overheadGoal, 0.0001, |
| 33 "Loop until timer overhead is at most this fraction of our measurm
ents."); | 39 "Loop until timer overhead is at most this fraction of our measurm
ents."); |
| 34 DEFINE_string(match, "", "The usual filters on file names of benchmarks to measu
re."); | 40 DEFINE_string(match, "", "The usual filters on file names of benchmarks to measu
re."); |
| 35 DEFINE_bool2(quiet, q, false, "Print only bench name and minimum sample."); | 41 DEFINE_bool2(quiet, q, false, "Print only bench name and minimum sample."); |
| 36 DEFINE_bool2(verbose, v, false, "Print all samples."); | 42 DEFINE_bool2(verbose, v, false, "Print all samples."); |
| 37 DEFINE_string(config, "nonrendering 8888 gpu", "Configs to measure. Options: " | 43 DEFINE_string(config, "nonrendering 8888 gpu", "Configs to measure. Options: " |
| 38 "565 8888 gpu nonrendering debug nullgpu msaa4 msaa16 nvprmsaa4 nv
prmsaa16 angle"); | 44 "565 8888 gpu nonrendering debug nullgpu msaa4 msaa16 nvprmsaa4 nv
prmsaa16 angle"); |
| 39 DEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU."); | 45 DEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU."); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 // | 103 // |
| 98 // Doing some math, we get: | 104 // Doing some math, we get: |
| 99 // | 105 // |
| 100 // (overhead / FLAGS_overheadGoal) - overhead | 106 // (overhead / FLAGS_overheadGoal) - overhead |
| 101 // ------------------------------------------ < N | 107 // ------------------------------------------ < N |
| 102 // bench_plus_overhead - overhead) | 108 // bench_plus_overhead - overhead) |
| 103 // | 109 // |
| 104 // Luckily, this also works well in practice. :) | 110 // Luckily, this also works well in practice. :) |
| 105 const double numer = overhead / FLAGS_overheadGoal - overhead; | 111 const double numer = overhead / FLAGS_overheadGoal - overhead; |
| 106 const double denom = bench_plus_overhead - overhead; | 112 const double denom = bench_plus_overhead - overhead; |
| 107 const int loops = (int)ceil(numer / denom); | 113 const int loops = FLAGS_runOnce ? 1 : (int)ceil(numer / denom); |
| 108 | 114 |
| 109 for (int i = 0; i < FLAGS_samples; i++) { | 115 for (int i = 0; i < FLAGS_samples; i++) { |
| 110 samples[i] = time(loops, bench, canvas, NULL) / loops; | 116 samples[i] = time(loops, bench, canvas, NULL) / loops; |
| 111 } | 117 } |
| 112 return loops; | 118 return loops; |
| 113 } | 119 } |
| 114 | 120 |
| 115 #if SK_SUPPORT_GPU | 121 #if SK_SUPPORT_GPU |
| 116 static int gpu_bench(SkGLContextHelper* gl, | 122 static int gpu_bench(SkGLContextHelper* gl, |
| 117 Benchmark* bench, | 123 Benchmark* bench, |
| 118 SkCanvas* canvas, | 124 SkCanvas* canvas, |
| 119 double* samples) { | 125 double* samples) { |
| 120 // Make sure we're done with whatever came before. | 126 // Make sure we're done with whatever came before. |
| 121 SK_GL(*gl, Finish()); | 127 SK_GL(*gl, Finish()); |
| 122 | 128 |
| 123 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. | 129 // First, figure out how many loops it'll take to get a frame up to FLAGS_gp
uMs. |
| 124 int loops = 1; | 130 int loops = 1; |
| 125 double elapsed = 0; | 131 if (!FLAGS_runOnce) { |
| 126 do { | 132 double elapsed = 0; |
| 127 loops *= 2; | 133 do { |
| 128 // If the GPU lets frames lag at all, we need to make sure we're timing | 134 loops *= 2; |
| 129 // _this_ round, not still timing last round. We force this by looping | 135 // If the GPU lets frames lag at all, we need to make sure we're tim
ing |
| 130 // more times than any reasonable GPU will allow frames to lag. | 136 // _this_ round, not still timing last round. We force this by loop
ing |
| 131 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 137 // more times than any reasonable GPU will allow frames to lag. |
| 132 elapsed = time(loops, bench, canvas, gl); | 138 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { |
| 133 } | 139 elapsed = time(loops, bench, canvas, gl); |
| 134 } while (elapsed < FLAGS_gpuMs); | 140 } |
| 141 } while (elapsed < FLAGS_gpuMs); |
| 135 | 142 |
| 136 // We've overshot at least a little. Scale back linearly. | 143 // We've overshot at least a little. Scale back linearly. |
| 137 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); | 144 loops = (int)ceil(loops * FLAGS_gpuMs / elapsed); |
| 138 | 145 |
| 139 // Might as well make sure we're not still timing our calibration. | 146 // Might as well make sure we're not still timing our calibration. |
| 140 SK_GL(*gl, Finish()); | 147 SK_GL(*gl, Finish()); |
| 148 } |
| 141 | 149 |
| 142 // Pretty much the same deal as the calibration: do some warmup to make | 150 // Pretty much the same deal as the calibration: do some warmup to make |
| 143 // sure we're timing steady-state pipelined frames. | 151 // sure we're timing steady-state pipelined frames. |
| 144 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { | 152 for (int i = 0; i < FLAGS_gpuFrameLag; i++) { |
| 145 time(loops, bench, canvas, gl); | 153 time(loops, bench, canvas, gl); |
| 146 } | 154 } |
| 147 | 155 |
| 148 // Now, actually do the timing! | 156 // Now, actually do the timing! |
| 149 for (int i = 0; i < FLAGS_samples; i++) { | 157 for (int i = 0; i < FLAGS_samples; i++) { |
| 150 samples[i] = time(loops, bench, canvas, gl) / loops; | 158 samples[i] = time(loops, bench, canvas, gl) / loops; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 log->option("build", "RELEASE"); | 253 log->option("build", "RELEASE"); |
| 246 #endif | 254 #endif |
| 247 } | 255 } |
| 248 | 256 |
| 249 int tool_main(int argc, char** argv); | 257 int tool_main(int argc, char** argv); |
| 250 int tool_main(int argc, char** argv) { | 258 int tool_main(int argc, char** argv) { |
| 251 SetupCrashHandler(); | 259 SetupCrashHandler(); |
| 252 SkAutoGraphics ag; | 260 SkAutoGraphics ag; |
| 253 SkCommandLineFlags::Parse(argc, argv); | 261 SkCommandLineFlags::Parse(argc, argv); |
| 254 | 262 |
| 263 if (FLAGS_runOnce) { |
| 264 FLAGS_samples = 1; |
| 265 FLAGS_gpuFrameLag = 0; |
| 266 } |
| 267 |
| 255 MultiResultsWriter log; | 268 MultiResultsWriter log; |
| 256 SkAutoTDelete<JSONResultsWriter> json; | 269 SkAutoTDelete<JSONResultsWriter> json; |
| 257 if (!FLAGS_outResultsFile.isEmpty()) { | 270 if (!FLAGS_outResultsFile.isEmpty()) { |
| 258 json.reset(SkNEW(JSONResultsWriter(FLAGS_outResultsFile[0]))); | 271 json.reset(SkNEW(JSONResultsWriter(FLAGS_outResultsFile[0]))); |
| 259 log.add(json.get()); | 272 log.add(json.get()); |
| 260 } | 273 } |
| 261 CallEnd<MultiResultsWriter> ender(log); | 274 CallEnd<MultiResultsWriter> ender(log); |
| 262 fill_static_options(&log); | 275 fill_static_options(&log); |
| 263 | 276 |
| 264 const double overhead = estimate_timer_overhead(); | 277 const double overhead = estimate_timer_overhead(); |
| 265 SkAutoTMalloc<double> samples(FLAGS_samples); | 278 SkAutoTMalloc<double> samples(FLAGS_samples); |
| 266 | 279 |
| 267 if (FLAGS_verbose) { | 280 if (FLAGS_runOnce) { |
| 281 SkDebugf("--runOnce is true; times would only be misleading so we won't
print them.\n"); |
| 282 } else if (FLAGS_verbose) { |
| 268 // No header. | 283 // No header. |
| 269 } else if (FLAGS_quiet) { | 284 } else if (FLAGS_quiet) { |
| 270 SkDebugf("median\tbench\tconfig\n"); | 285 SkDebugf("median\tbench\tconfig\n"); |
| 271 } else { | 286 } else { |
| 272 SkDebugf("loops\tmin\tmedian\tmean\tmax\tstddev\tsamples\tconfig\tbench\
n"); | 287 SkDebugf("loops\tmin\tmedian\tmean\tmax\tstddev\tsamples\tconfig\tbench\
n"); |
| 273 } | 288 } |
| 274 | 289 |
| 275 for (const BenchRegistry* r = BenchRegistry::Head(); r != NULL; r = r->next(
)) { | 290 for (const BenchRegistry* r = BenchRegistry::Head(); r != NULL; r = r->next(
)) { |
| 276 SkAutoTDelete<Benchmark> bench(r->factory()(NULL)); | 291 SkAutoTDelete<Benchmark> bench(r->factory()(NULL)); |
| 277 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { | 292 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 298 | 313 |
| 299 const char* config = targets[j]->config; | 314 const char* config = targets[j]->config; |
| 300 | 315 |
| 301 log.config(config); | 316 log.config(config); |
| 302 log.timer("min_ms", stats.min); | 317 log.timer("min_ms", stats.min); |
| 303 log.timer("median_ms", stats.median); | 318 log.timer("median_ms", stats.median); |
| 304 log.timer("mean_ms", stats.mean); | 319 log.timer("mean_ms", stats.mean); |
| 305 log.timer("max_ms", stats.max); | 320 log.timer("max_ms", stats.max); |
| 306 log.timer("stddev_ms", sqrt(stats.var)); | 321 log.timer("stddev_ms", sqrt(stats.var)); |
| 307 | 322 |
| 308 if (FLAGS_verbose) { | 323 if (FLAGS_runOnce) { |
| 324 if (targets.count() == 1) { |
| 325 config = ""; // Only print the config if we run the same ben
ch on more than one. |
| 326 } |
| 327 SkDebugf("%s\t%s\n", bench->getName(), config); |
| 328 } else if (FLAGS_verbose) { |
| 309 for (int i = 0; i < FLAGS_samples; i++) { | 329 for (int i = 0; i < FLAGS_samples; i++) { |
| 310 SkDebugf("%s ", humanize(samples[i]).c_str()); | 330 SkDebugf("%s ", humanize(samples[i]).c_str()); |
| 311 } | 331 } |
| 312 SkDebugf("%s\n", bench->getName()); | 332 SkDebugf("%s\n", bench->getName()); |
| 313 } else if (FLAGS_quiet) { | 333 } else if (FLAGS_quiet) { |
| 314 if (targets.count() == 1) { | 334 if (targets.count() == 1) { |
| 315 config = ""; // Only print the config if we run the same ben
ch on more than one. | 335 config = ""; // Only print the config if we run the same ben
ch on more than one. |
| 316 } | 336 } |
| 317 SkDebugf("%s\t%s\t%s\n", humanize(stats.median).c_str(), bench->
getName(), config); | 337 SkDebugf("%s\t%s\t%s\n", humanize(stats.median).c_str(), bench->
getName(), config); |
| 318 } else { | 338 } else { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 334 } | 354 } |
| 335 | 355 |
| 336 return 0; | 356 return 0; |
| 337 } | 357 } |
| 338 | 358 |
| 339 #if !defined SK_BUILD_FOR_IOS | 359 #if !defined SK_BUILD_FOR_IOS |
| 340 int main(int argc, char * const argv[]) { | 360 int main(int argc, char * const argv[]) { |
| 341 return tool_main(argc, (char**) argv); | 361 return tool_main(argc, (char**) argv); |
| 342 } | 362 } |
| 343 #endif | 363 #endif |
| OLD | NEW |