Index: tools/skpbench/skpbench.cpp |
diff --git a/tools/skpbench/skpbench.cpp b/tools/skpbench/skpbench.cpp |
index 063261a44869af2a2a6a3fec0a76395024ead450..0eed6b16019d9f99e93226b24cb379813f716d54 100644 |
--- a/tools/skpbench/skpbench.cpp |
+++ b/tools/skpbench/skpbench.cpp |
@@ -30,14 +30,11 @@ |
* No tiling, looping, or other fanciness is used; it just draws the skp whole into a size-matched |
* render target and syncs the GPU after each draw. |
* |
- * The results consist of a fixed amount of samples (--samples). A sample is defined as the number |
- * of frames rendered within a set amount of time (--sampleMs). |
- * |
* Currently, only GPU configs are supported. |
*/ |
-DEFINE_int32(samples, 101, "number of samples to collect"); |
-DEFINE_int32(sampleMs, 50, "duration of each sample"); |
+DEFINE_int32(duration, 5000, "number of milliseconds to run the benchmark"); |
+DEFINE_int32(sampleMs, 50, "minimum duration of a sample"); |
DEFINE_bool(fps, false, "use fps instead of ms"); |
DEFINE_string(skp, "", "path to a single .skp file to benchmark"); |
DEFINE_string(png, "", "if set, save a .png proof to disk at this file location"); |
@@ -82,10 +79,8 @@ static void exitf(ExitErr, const char* format, ...); |
static void run_benchmark(const SkGpuFenceSync* sync, SkCanvas* canvas, const SkPicture* skp, |
std::vector<Sample>* samples) { |
using clock = Sample::clock; |
- std::chrono::milliseconds sampleMs(FLAGS_sampleMs); |
- |
- samples->clear(); |
- samples->resize(FLAGS_samples); |
+ const clock::duration sampleDuration = std::chrono::milliseconds(FLAGS_sampleMs); |
+ const clock::duration benchDuration = std::chrono::milliseconds(FLAGS_duration); |
// Prime the graphics pipe. |
SkPlatformGpuFence frameN_minus_2, frameN_minus_1; |
@@ -102,10 +97,14 @@ static void run_benchmark(const SkGpuFenceSync* sync, SkCanvas* canvas, const Sk |
wait_fence_and_delete(sync, frame0); |
} |
- clock::time_point start = clock::now(); |
+ clock::time_point now = clock::now(); |
+ const clock::time_point endTime = now + benchDuration; |
+ |
+ do { |
+ clock::time_point sampleStart = now; |
+ samples->emplace_back(); |
+ Sample& sample = samples->back(); |
- for (Sample& sample : *samples) { |
- clock::time_point end; |
do { |
draw_skp_and_flush(canvas, skp); |
@@ -114,18 +113,11 @@ static void run_benchmark(const SkGpuFenceSync* sync, SkCanvas* canvas, const Sk |
frameN_minus_2 = frameN_minus_1; |
frameN_minus_1 = insert_verified_fence(sync); |
- end = clock::now(); |
- sample.fDuration = end - start; |
+ now = clock::now(); |
+ sample.fDuration = now - sampleStart; |
++sample.fFrames; |
- } while (sample.fDuration < sampleMs); |
- |
- if (FLAGS_verbosity >= 5) { |
- fprintf(stderr, "%.4g%s [ms=%.4g frames=%i]\n", |
- sample.value(), Sample::metric(), sample.ms(), sample.fFrames); |
- } |
- |
- start = end; |
- } |
+ } while (sample.fDuration < sampleDuration); |
+ } while (now < endTime || 0 == samples->size() % 2); |
sync->deleteFence(frameN_minus_2); |
sync->deleteFence(frameN_minus_1); |
@@ -145,19 +137,19 @@ void print_result(const std::vector<Sample>& samples, const char* config, const |
values.push_back(sample.value()); |
} |
std::sort(values.begin(), values.end()); |
- const double median = values[values.size() / 2]; |
+ const double medianValue = values[values.size() / 2]; |
+ const double accumValue = accum.value(); |
- const double meanValue = accum.value(); |
double variance = 0; |
- for (const Sample& sample : samples) { |
- const double delta = sample.value() - meanValue; |
+ for (double value : values) { |
+ const double delta = value - accumValue; |
variance += delta * delta; |
} |
- variance /= samples.size(); |
+ variance /= values.size(); |
// Technically, this is the relative standard deviation. |
- const double stddev = 100/*%*/ * sqrt(variance) / meanValue; |
+ const double stddev = 100/*%*/ * sqrt(variance) / accumValue; |
- printf(resultFormat, median, accum.value(), values.back(), values.front(), stddev, |
+ printf(resultFormat, medianValue, accumValue, values.back(), values.front(), stddev, |
Sample::metric(), values.size(), FLAGS_sampleMs, config, bench); |
printf("\n"); |
fflush(stdout); |
@@ -171,15 +163,9 @@ int main(int argc, char** argv) { |
if (!FLAGS_suppressHeader) { |
printf("%s\n", header); |
} |
- if (FLAGS_samples <= 0) { |
+ if (FLAGS_duration <= 0) { |
exit(0); // This can be used to print the header and quit. |
} |
- if (0 == FLAGS_samples % 2) { |
- fprintf(stderr, "WARNING: even number of samples requested (%i); " |
- "using %i so there can be a true median.\n", |
- FLAGS_samples, FLAGS_samples + 1); |
- ++FLAGS_samples; |
- } |
// Parse the config. |
const SkCommandLineConfigGpu* config = nullptr; // Initialize for spurious warning. |
@@ -251,8 +237,15 @@ int main(int argc, char** argv) { |
width, height, config->getTag().c_str()); |
} |
- // Run the benchmark. |
std::vector<Sample> samples; |
+ if (FLAGS_sampleMs > 0) { |
+ // +1 because we might take one more sample in order to have an odd number. |
+ samples.reserve(1 + (FLAGS_duration + FLAGS_sampleMs - 1) / FLAGS_sampleMs); |
+ } else { |
+ samples.reserve(2 * FLAGS_duration); |
+ } |
+ |
+ // Run the benchmark. |
SkCanvas* canvas = surface->getCanvas(); |
canvas->translate(-skp->cullRect().x(), -skp->cullRect().y()); |
run_benchmark(testCtx->fenceSync(), canvas, skp.get(), &samples); |