Chromium Code Reviews| Index: tools/skpbench/skpbench.cpp |
| diff --git a/tools/skpbench/skpbench.cpp b/tools/skpbench/skpbench.cpp |
| index 063261a44869af2a2a6a3fec0a76395024ead450..3c7bd9e6f0b8ec62e981684a7c03ed82bc9a389e 100644 |
| --- a/tools/skpbench/skpbench.cpp |
| +++ b/tools/skpbench/skpbench.cpp |
| @@ -5,6 +5,7 @@ |
| * found in the LICENSE file. |
| */ |
| +#include "GrAllocator.h" |
| #include "GrContextFactory.h" |
| #include "SkCanvas.h" |
| #include "SkOSFile.h" |
| @@ -30,14 +31,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"); |
| @@ -80,12 +78,10 @@ static SkString join(const SkCommandLineFlags::StringArray&); |
| static void exitf(ExitErr, const char* format, ...); |
| static void run_benchmark(const SkGpuFenceSync* sync, SkCanvas* canvas, const SkPicture* skp, |
| - std::vector<Sample>* samples) { |
| + GrTAllocator<Sample>* samples) { |
|
bsalomon
2016/09/28 18:51:16
Why the change to GrTAllocator?
csmartdalton
2016/09/28 19:17:54
Because with "--sampleMs 0" we don't know an upper
|
| 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 +98,13 @@ 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; |
| + Sample& sample = samples->push_back(); |
| - for (Sample& sample : *samples) { |
| - clock::time_point end; |
| do { |
| draw_skp_and_flush(canvas, skp); |
| @@ -114,50 +113,43 @@ 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->count() % 2); |
| sync->deleteFence(frameN_minus_2); |
| sync->deleteFence(frameN_minus_1); |
| } |
| -void print_result(const std::vector<Sample>& samples, const char* config, const char* bench) { |
| - if (0 == (samples.size() % 2)) { |
| +void print_result(const GrTAllocator<Sample>& samples, const char* config, const char* bench) { |
| + if (0 == (samples.count() % 2)) { |
| exitf(ExitErr::kSoftware, "attempted to gather stats on even number of samples"); |
| } |
| Sample accum = Sample(); |
| std::vector<double> values; |
| - values.reserve(samples.size()); |
| - for (const Sample& sample : samples) { |
| - accum.fFrames += sample.fFrames; |
| - accum.fDuration += sample.fDuration; |
| - values.push_back(sample.value()); |
| + values.reserve(samples.count()); |
| + for (GrTAllocator<Sample>::Iter it(&samples); it.next();) { |
| + accum.fFrames += it->fFrames; |
| + accum.fDuration += it->fDuration; |
| + values.push_back(it->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,16 @@ int main(int argc, char** argv) { |
| width, height, config->getTag().c_str()); |
| } |
| + int reserve; |
| + if (FLAGS_sampleMs > 0) { |
| + // +1 because we might take one more sample in order to have an odd number. |
| + reserve = 1 + (FLAGS_duration + FLAGS_sampleMs - 1) / FLAGS_sampleMs; |
| + } else { |
| + reserve = 2 * FLAGS_duration; |
| + } |
| + GrTAllocator<Sample> samples(reserve); |
| + |
| // Run the benchmark. |
| - std::vector<Sample> samples; |
| SkCanvas* canvas = surface->getCanvas(); |
| canvas->translate(-skp->cullRect().x(), -skp->cullRect().y()); |
| run_benchmark(testCtx->fenceSync(), canvas, skp.get(), &samples); |