nanobench.cpp revision afb4379dbca4d4d3824ace183a7348d24bc1589f
1f372321de3d4183de5b9ca436e677e471e358f31mtklein/*
2f372321de3d4183de5b9ca436e677e471e358f31mtklein * Copyright 2014 Google Inc.
3f372321de3d4183de5b9ca436e677e471e358f31mtklein *
4f372321de3d4183de5b9ca436e677e471e358f31mtklein * Use of this source code is governed by a BSD-style license that can be
5f372321de3d4183de5b9ca436e677e471e358f31mtklein * found in the LICENSE file.
6f372321de3d4183de5b9ca436e677e471e358f31mtklein */
7f372321de3d4183de5b9ca436e677e471e358f31mtklein
8bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#include <ctype.h>
9bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
10f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Benchmark.h"
11f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "CrashHandler.h"
12e714e75c725c987fe682a1f5473224fe3e80380dmtklein#include "GMBench.h"
13afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein#include "ProcStats.h"
1460317d0ffb5053df7b08a627d6decd11b684e80dmtklein#include "ResultsWriter.h"
1592007583e43115998412ac8b0a06cc2780eb025cmtklein#include "SKPBench.h"
16f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Stats.h"
17f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Timer.h"
18f372321de3d4183de5b9ca436e677e471e358f31mtklein
1992007583e43115998412ac8b0a06cc2780eb025cmtklein#include "SkOSFile.h"
20f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkCanvas.h"
2117f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark#include "SkCommonFlags.h"
22f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkForceLinking.h"
23f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkGraphics.h"
24f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkString.h"
25f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkSurface.h"
26f372321de3d4183de5b9ca436e677e471e358f31mtklein
27bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
28bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    #include "gl/GrGLDefines.h"
29bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    #include "GrContextFactory.h"
3069a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    SkAutoTDelete<GrContextFactory> gGrFactory;
31bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
32bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
33f372321de3d4183de5b9ca436e677e471e358f31mtklein__SK_FORCE_IMAGE_DECODER_LINKING;
34f372321de3d4183de5b9ca436e677e471e358f31mtklein
356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic const int kAutoTuneLoops = -1;
366eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
37b511042bb07a6a289b0d1146cb57f6e8b80580d6mtkleinstatic const int kDefaultLoops =
386eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon#ifdef SK_DEBUG
396eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    1;
40a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#else
416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    kAutoTuneLoops;
42a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#endif
43a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic SkString loops_help_txt() {
456eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString help;
466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    help.printf("Number of times to run each bench. Set this to %d to auto-"
476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                "tune for each bench. Timings are only reported when auto-tuning.",
486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                kAutoTuneLoops);
496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return help;
506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonDEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str());
536eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
54f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(samples, 10, "Number of samples to measure for each bench.");
55f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead.");
56f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_double(overheadGoal, 0.0001,
57f372321de3d4183de5b9ca436e677e471e358f31mtklein              "Loop until timer overhead is at most this fraction of our measurments.");
58bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU.");
59bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allows to lag.");
6012b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevskiDEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
6112b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski                                          "software path rendering.");
62f372321de3d4183de5b9ca436e677e471e358f31mtklein
6360317d0ffb5053df7b08a627d6decd11b684e80dmtkleinDEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
6455b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxCalibrationAttempts, 3,
6555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein             "Try up to this many times to guess loops for a bench, or skip the bench.");
6655b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this.");
6794e51567dd691c3e1e8dfa6005a301d72cecf48emtkleinDEFINE_string(key, "",
6894e51567dd691c3e1e8dfa6005a301d72cecf48emtklein              "Space-separated key/value pairs to add to JSON identifying this bench config.");
6994e51567dd691c3e1e8dfa6005a301d72cecf48emtkleinDEFINE_string(options, "",
7094e51567dd691c3e1e8dfa6005a301d72cecf48emtklein              "Space-separated option/value pairs to add to JSON, logging extra info.");
71bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorioDEFINE_string(gitHash, "", "Git hash to add to JSON.");
7260317d0ffb5053df7b08a627d6decd11b684e80dmtklein
7392007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs.");
7492007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(scales, "1.0", "Space-separated scales for SKPs.");
7592007583e43115998412ac8b0a06cc2780eb025cmtklein
76f372321de3d4183de5b9ca436e677e471e358f31mtkleinstatic SkString humanize(double ms) {
77f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (ms > 1e+3) return SkStringPrintf("%.3gs",  ms/1e3);
78f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (ms < 1e-3) return SkStringPrintf("%.3gns", ms*1e6);
796238688af0d758660d344ec047243d4efefd6f4dmtklein#ifdef SK_BUILD_FOR_WIN
806238688af0d758660d344ec047243d4efefd6f4dmtklein    if (ms < 1)    return SkStringPrintf("%.3gus", ms*1e3);
816238688af0d758660d344ec047243d4efefd6f4dmtklein#else
82f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (ms < 1)    return SkStringPrintf("%.3gµs", ms*1e3);
836238688af0d758660d344ec047243d4efefd6f4dmtklein#endif
84f372321de3d4183de5b9ca436e677e471e358f31mtklein    return SkStringPrintf("%.3gms", ms);
85f372321de3d4183de5b9ca436e677e471e358f31mtklein}
8655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein#define HUMANIZE(ms) humanize(ms).c_str()
87f372321de3d4183de5b9ca436e677e471e358f31mtklein
88bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContextHelper* gl) {
896eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (canvas) {
906eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        canvas->clear(SK_ColorWHITE);
916eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
92f372321de3d4183de5b9ca436e677e471e358f31mtklein    WallTimer timer;
93bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    timer.start();
94bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    if (bench) {
95bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        bench->draw(loops, canvas);
96f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
97f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (canvas) {
98f372321de3d4183de5b9ca436e677e471e358f31mtklein        canvas->flush();
99f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
100bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
101bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    if (gl) {
102bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        SK_GL(*gl, Flush());
103bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        gl->swapBuffers();
104bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
105bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
106bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    timer.end();
107bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return timer.fWall;
108f372321de3d4183de5b9ca436e677e471e358f31mtklein}
109f372321de3d4183de5b9ca436e677e471e358f31mtklein
110bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double estimate_timer_overhead() {
111bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    double overhead = 0;
112bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_overheadLoops; i++) {
113bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        overhead += time(1, NULL, NULL, NULL);
114bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
115bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return overhead / FLAGS_overheadLoops;
116bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
117f372321de3d4183de5b9ca436e677e471e358f31mtklein
11855b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinstatic int clamp_loops(int loops) {
11955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops < 1) {
12055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("ERROR: clamping loops from %d to 1.\n", loops);
12155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return 1;
12255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
12355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops > FLAGS_maxLoops) {
12455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops);
12555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return FLAGS_maxLoops;
12655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
12755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    return loops;
12855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein}
12955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein
1306eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic bool write_canvas_png(SkCanvas* canvas, const SkString& filename) {
1316eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (filename.isEmpty()) {
1326eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1336eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1346eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kUnknown_SkColorType == canvas->imageInfo().fColorType) {
1356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1366eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1376eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkBitmap bmp;
1386eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    bmp.setInfo(canvas->imageInfo());
1396eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!canvas->readPixels(&bmp, 0, 0)) {
1406eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't read canvas pixels.\n");
1416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1426eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1436eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString dir = SkOSPath::Dirname(filename.c_str());
1446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!sk_mkdir(dir.c_str())) {
1456eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't make dir %s.\n", dir.c_str());
1466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkFILEWStream stream(filename.c_str());
1496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!stream.isValid()) {
1506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't write %s.\n", filename.c_str());
1516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1536eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) {
1546eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't encode a PNG.\n");
1556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1566eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1576eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return true;
1586eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
1596eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
1606eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic int kFailedLoops = -2;
161bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas, double* samples) {
162bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First figure out approximately how many loops of bench it takes to make overhead negligible.
1632069e220034f09aad2f68b262f395e7c25b3d178mtklein    double bench_plus_overhead = 0.0;
16455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    int round = 0;
1656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == FLAGS_loops) {
1666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        while (bench_plus_overhead < overhead) {
1676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (round++ == FLAGS_maxCalibrationAttempts) {
1686eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n",
1696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                         bench->getName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead));
1706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                return kFailedLoops;
1716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
1726eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            bench_plus_overhead = time(1, bench, canvas, NULL);
17355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        }
1742069e220034f09aad2f68b262f395e7c25b3d178mtklein    }
175f372321de3d4183de5b9ca436e677e471e358f31mtklein
176bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Later we'll just start and stop the timer once but loop N times.
177f372321de3d4183de5b9ca436e677e471e358f31mtklein    // We'll pick N to make timer overhead negligible:
178f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
179bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //          overhead
180bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  -------------------------  < FLAGS_overheadGoal
181bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  overhead + N * Bench Time
182f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
183bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // where bench_plus_overhead ≈ overhead + Bench Time.
184f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
185f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Doing some math, we get:
186f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
187bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  (overhead / FLAGS_overheadGoal) - overhead
188bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  ------------------------------------------  < N
189bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //       bench_plus_overhead - overhead)
190f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
191f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Luckily, this also works well in practice. :)
1926eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    int loops = FLAGS_loops;
1936eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
1946eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double numer = overhead / FLAGS_overheadGoal - overhead;
1956eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double denom = bench_plus_overhead - overhead;
1966eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = (int)ceil(numer / denom);
1976eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1986eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    loops = clamp_loops(loops);
199bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
200bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_samples; i++) {
201bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        samples[i] = time(loops, bench, canvas, NULL) / loops;
202bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
203bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
204f372321de3d4183de5b9ca436e677e471e358f31mtklein}
205f372321de3d4183de5b9ca436e677e471e358f31mtklein
206bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
207bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic int gpu_bench(SkGLContextHelper* gl,
208bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     Benchmark* bench,
209bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     SkCanvas* canvas,
210bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     double* samples) {
211c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    gl->makeCurrent();
212bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Make sure we're done with whatever came before.
2139bc86ed0523e154f6f4329f43c15012f930e06d7mtklein    SK_GL(*gl, Finish());
214bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
215bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs.
2166eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    int loops = FLAGS_loops;
2176eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
2186eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = 1;
219a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        double elapsed = 0;
220a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        do {
221a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            loops *= 2;
222a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // If the GPU lets frames lag at all, we need to make sure we're timing
223a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // _this_ round, not still timing last round.  We force this by looping
224a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // more times than any reasonable GPU will allow frames to lag.
225a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
226a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                elapsed = time(loops, bench, canvas, gl);
227a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            }
228a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        } while (elapsed < FLAGS_gpuMs);
229a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
230a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // We've overshot at least a little.  Scale back linearly.
231a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
232a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
233a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // Might as well make sure we're not still timing our calibration.
234a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        SK_GL(*gl, Finish());
235a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
23655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    loops = clamp_loops(loops);
237bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
238bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Pretty much the same deal as the calibration: do some warmup to make
239bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // sure we're timing steady-state pipelined frames.
240bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
241bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        time(loops, bench, canvas, gl);
242f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
243bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
244bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Now, actually do the timing!
245bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_samples; i++) {
246bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        samples[i] = time(loops, bench, canvas, gl) / loops;
247bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
248bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
249f372321de3d4183de5b9ca436e677e471e358f31mtklein}
250bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
251bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
252bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic SkString to_lower(const char* str) {
253bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkString lower(str);
254bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (size_t i = 0; i < lower.size(); i++) {
255bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        lower[i] = tolower(lower[i]);
256bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
257bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return lower;
258bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
259bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
260c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstruct Config {
261c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    const char* name;
262bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    Benchmark::Backend backend;
263c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkColorType color;
264c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkAlphaType alpha;
265c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    int samples;
266c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
267c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    GrContextFactory::GLContextType ctxType;
268c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
269c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    int bogusInt;
270c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
271c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon};
272c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
273c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstruct Target {
274c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    explicit Target(const Config& c) : config(c) {}
275c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    const Config config;
276bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkAutoTDelete<SkSurface> surface;
277bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
278bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkGLContextHelper* gl;
279bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
280bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein};
281f372321de3d4183de5b9ca436e677e471e358f31mtklein
282c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_cpu_config_allowed(const char* name) {
283bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_config.count(); i++) {
284c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (to_lower(FLAGS_config[i]).equals(name)) {
285c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            return true;
286bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        }
287f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
288c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
289bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
290f372321de3d4183de5b9ca436e677e471e358f31mtklein
291c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
292c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_gpu_config_allowed(const char* name, GrContextFactory::GLContextType ctxType,
293c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                  int sampleCnt) {
294c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!is_cpu_config_allowed(name)) {
295c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return false;
296c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
29769a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    if (const GrContext* ctx = gGrFactory->get(ctxType)) {
298c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return sampleCnt <= ctx->getMaxSampleCount();
299c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
300c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
301c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
302c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
303c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
304c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
305c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType GrContextFactory::kNative_GLContextType
306c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
307c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType 0
308e714e75c725c987fe682a1f5473224fe3e80380dmtklein#endif
309c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
310c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Append all configs that are enabled and supported.
311c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_configs(SkTDArray<Config>* configs) {
312c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    #define CPU_CONFIG(name, backend, color, alpha)                                               \
313c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (is_cpu_config_allowed(#name)) {                                                       \
314c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = { #name, Benchmark::backend, color, alpha, 0, kBogusGLContextType };  \
315c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                                                \
316f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
317e714e75c725c987fe682a1f5473224fe3e80380dmtklein
31840b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_cpu) {
319c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
320c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
321c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
32240b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
323f372321de3d4183de5b9ca436e677e471e358f31mtklein
324bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
325c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    #define GPU_CONFIG(name, ctxType, samples)                                   \
326c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (is_gpu_config_allowed(#name, GrContextFactory::ctxType, samples)) {  \
327c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = {                                                    \
328c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                #name,                                                           \
329c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend,                                         \
330c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kN32_SkColorType,                                                \
331c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kPremul_SkAlphaType,                                             \
332c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                samples,                                                         \
333c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                GrContextFactory::ctxType };                                     \
334c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                               \
335f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
336e714e75c725c987fe682a1f5473224fe3e80380dmtklein
33740b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_gpu) {
338c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(gpu, kNative_GLContextType, 0)
339c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(msaa4, kNative_GLContextType, 4)
340c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(msaa16, kNative_GLContextType, 16)
341c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4)
342c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16)
343c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(debug, kDebug_GLContextType, 0)
344c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nullgpu, kNull_GLContextType, 0)
3453b4d077fba1ad037536db198608a940c47d91888bsalomon#ifdef SK_ANGLE
3463b4d077fba1ad037536db198608a940c47d91888bsalomon        GPU_CONFIG(angle, kANGLE_GLContextType, 0)
3473b4d077fba1ad037536db198608a940c47d91888bsalomon#endif
34840b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
349bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
350f372321de3d4183de5b9ca436e677e471e358f31mtklein}
351f372321de3d4183de5b9ca436e677e471e358f31mtklein
352c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// If bench is enabled for config, returns a Target* for it, otherwise NULL.
353c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic Target* is_enabled(Benchmark* bench, const Config& config) {
354c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!bench->isSuitableFor(config.backend)) {
355c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return NULL;
356c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
357c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
358c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkImageInfo info;
359c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    info.fAlphaType = config.alpha;
360c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    info.fColorType = config.color;
361c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    info.fWidth = bench->getSize().fX;
362c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    info.fHeight = bench->getSize().fY;
363c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
364c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    Target* target = new Target(config);
365c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
366c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (Benchmark::kRaster_Backend == config.backend) {
367c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        target->surface.reset(SkSurface::NewRaster(info));
368c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
369c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
370c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    else if (Benchmark::kGPU_Backend == config.backend) {
37169a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski        target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.ctxType), info,
372c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                                         config.samples));
37369a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski        target->gl = gGrFactory->getGLContext(config.ctxType);
374c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
375c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
376c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
377c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (Benchmark::kNonRendering_Backend != config.backend && !target->surface.get()) {
378c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        delete target;
379c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return NULL;
380c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
381c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return target;
382c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
383c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
384c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Creates targets for a benchmark and a set of configs.
385c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_targets(SkTDArray<Target*>* targets, Benchmark* b,
386c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                           const SkTDArray<Config>& configs) {
387c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    for (int i = 0; i < configs.count(); ++i) {
388c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (Target* t = is_enabled(b, configs[i])) {
389c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            targets->push(t);
390c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        }
391e714e75c725c987fe682a1f5473224fe3e80380dmtklein
392c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
393c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
394c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
39560317d0ffb5053df7b08a627d6decd11b684e80dmtkleinstatic void fill_static_options(ResultsWriter* log) {
39660317d0ffb5053df7b08a627d6decd11b684e80dmtklein#if defined(SK_BUILD_FOR_WIN32)
39760317d0ffb5053df7b08a627d6decd11b684e80dmtklein    log->option("system", "WIN32");
39860317d0ffb5053df7b08a627d6decd11b684e80dmtklein#elif defined(SK_BUILD_FOR_MAC)
39960317d0ffb5053df7b08a627d6decd11b684e80dmtklein    log->option("system", "MAC");
40060317d0ffb5053df7b08a627d6decd11b684e80dmtklein#elif defined(SK_BUILD_FOR_ANDROID)
40160317d0ffb5053df7b08a627d6decd11b684e80dmtklein    log->option("system", "ANDROID");
40260317d0ffb5053df7b08a627d6decd11b684e80dmtklein#elif defined(SK_BUILD_FOR_UNIX)
40360317d0ffb5053df7b08a627d6decd11b684e80dmtklein    log->option("system", "UNIX");
40460317d0ffb5053df7b08a627d6decd11b684e80dmtklein#else
40560317d0ffb5053df7b08a627d6decd11b684e80dmtklein    log->option("system", "other");
40660317d0ffb5053df7b08a627d6decd11b684e80dmtklein#endif
40760317d0ffb5053df7b08a627d6decd11b684e80dmtklein}
40860317d0ffb5053df7b08a627d6decd11b684e80dmtklein
409bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#if SK_SUPPORT_GPU
410bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregoriostatic void fill_gpu_options(ResultsWriter* log, SkGLContextHelper* ctx) {
41105c4560ab36447895d510655f927fcf123330497jcgregorio    const GrGLubyte* version;
412bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION));
413bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_VERSION", (const char*)(version));
414bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
415bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER));
416bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_RENDERER", (const char*) version);
417bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
418bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR));
419bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_VENDOR", (const char*) version);
420bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
421bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
422bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
423bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio}
424bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#endif
425bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
426e714e75c725c987fe682a1f5473224fe3e80380dmtkleinclass BenchmarkStream {
427e714e75c725c987fe682a1f5473224fe3e80380dmtkleinpublic:
42892007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream() : fBenches(BenchRegistry::Head())
42992007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fGMs(skiagm::GMRegistry::Head())
43092007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentScale(0)
43192007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentSKP(0) {
43292007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_skps.count(); i++) {
43392007583e43115998412ac8b0a06cc2780eb025cmtklein            if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
43492007583e43115998412ac8b0a06cc2780eb025cmtklein                fSKPs.push_back() = FLAGS_skps[i];
43592007583e43115998412ac8b0a06cc2780eb025cmtklein            } else {
43692007583e43115998412ac8b0a06cc2780eb025cmtklein                SkOSFile::Iter it(FLAGS_skps[i], ".skp");
43792007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString path;
43892007583e43115998412ac8b0a06cc2780eb025cmtklein                while (it.next(&path)) {
43992007583e43115998412ac8b0a06cc2780eb025cmtklein                    fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
44092007583e43115998412ac8b0a06cc2780eb025cmtklein                }
44192007583e43115998412ac8b0a06cc2780eb025cmtklein            }
44292007583e43115998412ac8b0a06cc2780eb025cmtklein        }
44392007583e43115998412ac8b0a06cc2780eb025cmtklein
44492007583e43115998412ac8b0a06cc2780eb025cmtklein        if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d",
44592007583e43115998412ac8b0a06cc2780eb025cmtklein                        &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) {
44692007583e43115998412ac8b0a06cc2780eb025cmtklein            SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]);
44792007583e43115998412ac8b0a06cc2780eb025cmtklein            exit(1);
44892007583e43115998412ac8b0a06cc2780eb025cmtklein        }
44992007583e43115998412ac8b0a06cc2780eb025cmtklein
45092007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_scales.count(); i++) {
45192007583e43115998412ac8b0a06cc2780eb025cmtklein            if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) {
45292007583e43115998412ac8b0a06cc2780eb025cmtklein                SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]);
45392007583e43115998412ac8b0a06cc2780eb025cmtklein                exit(1);
45492007583e43115998412ac8b0a06cc2780eb025cmtklein            }
45592007583e43115998412ac8b0a06cc2780eb025cmtklein        }
45692007583e43115998412ac8b0a06cc2780eb025cmtklein    }
457e714e75c725c987fe682a1f5473224fe3e80380dmtklein
45892007583e43115998412ac8b0a06cc2780eb025cmtklein    Benchmark* next() {
459e714e75c725c987fe682a1f5473224fe3e80380dmtklein        if (fBenches) {
460e714e75c725c987fe682a1f5473224fe3e80380dmtklein            Benchmark* bench = fBenches->factory()(NULL);
461e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fBenches = fBenches->next();
46292007583e43115998412ac8b0a06cc2780eb025cmtklein            fSourceType = "bench";
463e714e75c725c987fe682a1f5473224fe3e80380dmtklein            return bench;
464e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
46592007583e43115998412ac8b0a06cc2780eb025cmtklein
466e714e75c725c987fe682a1f5473224fe3e80380dmtklein        while (fGMs) {
467e714e75c725c987fe682a1f5473224fe3e80380dmtklein            SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL));
468e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fGMs = fGMs->next();
469e714e75c725c987fe682a1f5473224fe3e80380dmtklein            if (gm->getFlags() & skiagm::GM::kAsBench_Flag) {
47092007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "gm";
471e714e75c725c987fe682a1f5473224fe3e80380dmtklein                return SkNEW_ARGS(GMBench, (gm.detach()));
472e714e75c725c987fe682a1f5473224fe3e80380dmtklein            }
473e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
47492007583e43115998412ac8b0a06cc2780eb025cmtklein
47592007583e43115998412ac8b0a06cc2780eb025cmtklein        while (fCurrentScale < fScales.count()) {
47692007583e43115998412ac8b0a06cc2780eb025cmtklein            while (fCurrentSKP < fSKPs.count()) {
47792007583e43115998412ac8b0a06cc2780eb025cmtklein                const SkString& path = fSKPs[fCurrentSKP++];
47892007583e43115998412ac8b0a06cc2780eb025cmtklein
47992007583e43115998412ac8b0a06cc2780eb025cmtklein                // Not strictly necessary, as it will be checked again later,
48092007583e43115998412ac8b0a06cc2780eb025cmtklein                // but helps to avoid a lot of pointless work if we're going to skip it.
48192007583e43115998412ac8b0a06cc2780eb025cmtklein                if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path.c_str())) {
48292007583e43115998412ac8b0a06cc2780eb025cmtklein                    continue;
48392007583e43115998412ac8b0a06cc2780eb025cmtklein                }
48492007583e43115998412ac8b0a06cc2780eb025cmtklein
48592007583e43115998412ac8b0a06cc2780eb025cmtklein                SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path.c_str()));
48692007583e43115998412ac8b0a06cc2780eb025cmtklein                if (stream.get() == NULL) {
48792007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkDebugf("Could not read %s.\n", path.c_str());
48892007583e43115998412ac8b0a06cc2780eb025cmtklein                    exit(1);
48992007583e43115998412ac8b0a06cc2780eb025cmtklein                }
49092007583e43115998412ac8b0a06cc2780eb025cmtklein
49192007583e43115998412ac8b0a06cc2780eb025cmtklein                SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream.get()));
49292007583e43115998412ac8b0a06cc2780eb025cmtklein                if (pic.get() == NULL) {
49392007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkDebugf("Could not read %s as an SkPicture.\n", path.c_str());
49492007583e43115998412ac8b0a06cc2780eb025cmtklein                    exit(1);
49592007583e43115998412ac8b0a06cc2780eb025cmtklein                }
49692007583e43115998412ac8b0a06cc2780eb025cmtklein
49792007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString name = SkOSPath::Basename(path.c_str());
49892007583e43115998412ac8b0a06cc2780eb025cmtklein
49992007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "skp";
50092007583e43115998412ac8b0a06cc2780eb025cmtklein                return SkNEW_ARGS(SKPBench,
50192007583e43115998412ac8b0a06cc2780eb025cmtklein                        (name.c_str(), pic.get(), fClip, fScales[fCurrentScale]));
50292007583e43115998412ac8b0a06cc2780eb025cmtklein            }
50392007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentSKP = 0;
50492007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentScale++;
50592007583e43115998412ac8b0a06cc2780eb025cmtklein        }
50692007583e43115998412ac8b0a06cc2780eb025cmtklein
507e714e75c725c987fe682a1f5473224fe3e80380dmtklein        return NULL;
508e714e75c725c987fe682a1f5473224fe3e80380dmtklein    }
50992007583e43115998412ac8b0a06cc2780eb025cmtklein
51092007583e43115998412ac8b0a06cc2780eb025cmtklein    void fillCurrentOptions(ResultsWriter* log) const {
51192007583e43115998412ac8b0a06cc2780eb025cmtklein        log->configOption("source_type", fSourceType);
51292007583e43115998412ac8b0a06cc2780eb025cmtklein        if (0 == strcmp(fSourceType, "skp")) {
51392007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("clip",
51492007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop,
51592007583e43115998412ac8b0a06cc2780eb025cmtklein                                                  fClip.fRight, fClip.fBottom).c_str());
51692007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str());
51792007583e43115998412ac8b0a06cc2780eb025cmtklein        }
51892007583e43115998412ac8b0a06cc2780eb025cmtklein    }
51992007583e43115998412ac8b0a06cc2780eb025cmtklein
520e714e75c725c987fe682a1f5473224fe3e80380dmtkleinprivate:
521e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const BenchRegistry* fBenches;
522e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const skiagm::GMRegistry* fGMs;
52392007583e43115998412ac8b0a06cc2780eb025cmtklein    SkIRect            fClip;
52492007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkScalar> fScales;
52592007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkString> fSKPs;
52692007583e43115998412ac8b0a06cc2780eb025cmtklein
52792007583e43115998412ac8b0a06cc2780eb025cmtklein    const char* fSourceType;
52892007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentScale;
52992007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentSKP;
530e714e75c725c987fe682a1f5473224fe3e80380dmtklein};
531e714e75c725c987fe682a1f5473224fe3e80380dmtklein
53217f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main();
53317f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main() {
534f372321de3d4183de5b9ca436e677e471e358f31mtklein    SetupCrashHandler();
535f372321de3d4183de5b9ca436e677e471e358f31mtklein    SkAutoGraphics ag;
536f372321de3d4183de5b9ca436e677e471e358f31mtklein
53769a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#if SK_SUPPORT_GPU
53812b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    GrContext::Options grContextOpts;
53912b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
54012b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    gGrFactory.reset(SkNEW_ARGS(GrContextFactory, (grContextOpts)));
54169a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#endif
54269a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski
5436eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
544a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_samples     = 1;
545a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_gpuFrameLag = 0;
546a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
547a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
5486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!FLAGS_writePath.isEmpty()) {
5496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]);
5506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        if (!sk_mkdir(FLAGS_writePath[0])) {
5516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]);
5526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            FLAGS_writePath.set(0, NULL);
5536eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        }
5546eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
5556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
55660317d0ffb5053df7b08a627d6decd11b684e80dmtklein    MultiResultsWriter log;
557bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SkAutoTDelete<NanoJSONResultsWriter> json;
55860317d0ffb5053df7b08a627d6decd11b684e80dmtklein    if (!FLAGS_outResultsFile.isEmpty()) {
559bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        const char* gitHash = FLAGS_gitHash.isEmpty() ? "unknown-revision" : FLAGS_gitHash[0];
560bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        json.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0], gitHash)));
56160317d0ffb5053df7b08a627d6decd11b684e80dmtklein        log.add(json.get());
56260317d0ffb5053df7b08a627d6decd11b684e80dmtklein    }
56360317d0ffb5053df7b08a627d6decd11b684e80dmtklein    CallEnd<MultiResultsWriter> ender(log);
564bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
565bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    if (1 == FLAGS_key.count() % 2) {
566bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
567bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        return 1;
568bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
569bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    for (int i = 1; i < FLAGS_key.count(); i += 2) {
570bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        log.key(FLAGS_key[i-1], FLAGS_key[i]);
571bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
57294e51567dd691c3e1e8dfa6005a301d72cecf48emtklein
57360317d0ffb5053df7b08a627d6decd11b684e80dmtklein    fill_static_options(&log);
57494e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    if (1 == FLAGS_options.count() % 2) {
57594e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        SkDebugf("ERROR: --options must be passed with an even number of arguments.\n");
57694e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        return 1;
57794e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
57894e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    for (int i = 1; i < FLAGS_options.count(); i += 2) {
57994e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        log.option(FLAGS_options[i-1], FLAGS_options[i]);
58094e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
58160317d0ffb5053df7b08a627d6decd11b684e80dmtklein
582f372321de3d4183de5b9ca436e677e471e358f31mtklein    const double overhead = estimate_timer_overhead();
58355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead));
584912947737a973421f4c58682b6171cb5ee00ad3aMike Klein
585bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkAutoTMalloc<double> samples(FLAGS_samples);
586bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
5876eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
5886eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n");
589a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    } else if (FLAGS_verbose) {
590f372321de3d4183de5b9ca436e677e471e358f31mtklein        // No header.
591f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else if (FLAGS_quiet) {
59240b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        SkDebugf("median\tbench\tconfig\n");
593f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else {
594afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein        SkDebugf("maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\tsamples\tconfig\tbench\n");
595f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
596f372321de3d4183de5b9ca436e677e471e358f31mtklein
597c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkTDArray<Config> configs;
598c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    create_configs(&configs);
599c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
60092007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream benchStream;
60192007583e43115998412ac8b0a06cc2780eb025cmtklein    while (Benchmark* b = benchStream.next()) {
602e714e75c725c987fe682a1f5473224fe3e80380dmtklein        SkAutoTDelete<Benchmark> bench(b);
603f372321de3d4183de5b9ca436e677e471e358f31mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
604f372321de3d4183de5b9ca436e677e471e358f31mtklein            continue;
605f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
606f372321de3d4183de5b9ca436e677e471e358f31mtklein
607bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        SkTDArray<Target*> targets;
608c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        create_targets(&targets, bench.get(), configs);
609f372321de3d4183de5b9ca436e677e471e358f31mtklein
610bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        if (!targets.isEmpty()) {
611bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio            log.bench(bench->getName(), bench->getSize().fX, bench->getSize().fY);
612bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio            bench->preDraw();
613bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        }
614bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        for (int j = 0; j < targets.count(); j++) {
615bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein            SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL;
616c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            const char* config = targets[j]->config.name;
617bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
61892007583e43115998412ac8b0a06cc2780eb025cmtklein#if SK_DEBUG
61992007583e43115998412ac8b0a06cc2780eb025cmtklein            // skia:2797  Some SKPs SkASSERT in debug mode.  Skip them for now.
6206e33e232df34d74c62e51e7e30d3ce90f14b46damtklein            if (0 == strcmp("565", config) && SkStrContains(bench->getName(), ".skp")) {
6216e33e232df34d74c62e51e7e30d3ce90f14b46damtklein                SkDebugf("Skipping 565 %s.  See skia:2797\n", bench->getName());
62292007583e43115998412ac8b0a06cc2780eb025cmtklein                continue;
62392007583e43115998412ac8b0a06cc2780eb025cmtklein            }
62492007583e43115998412ac8b0a06cc2780eb025cmtklein#endif
62592007583e43115998412ac8b0a06cc2780eb025cmtklein
626bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein            const int loops =
627bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
628c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend == targets[j]->config.backend
629bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                ? gpu_bench(targets[j]->gl, bench.get(), canvas, samples.get())
630bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                :
631bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
632bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                 cpu_bench(       overhead, bench.get(), canvas, samples.get());
633f372321de3d4183de5b9ca436e677e471e358f31mtklein
6346eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (canvas && !FLAGS_writePath.isEmpty() && NULL != FLAGS_writePath[0]) {
6356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config);
6366eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getName());
6376eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename.append(".png");
6386eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                write_canvas_png(canvas, pngFilename);
6396eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
6406eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
6416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kFailedLoops == loops) {
6422069e220034f09aad2f68b262f395e7c25b3d178mtklein                // Can't be timed.  A warning note has already been printed.
643e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein                continue;
644e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            }
64560317d0ffb5053df7b08a627d6decd11b684e80dmtklein
646e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            Stats stats(samples.get(), FLAGS_samples);
64760317d0ffb5053df7b08a627d6decd11b684e80dmtklein            log.config(config);
64892007583e43115998412ac8b0a06cc2780eb025cmtklein            benchStream.fillCurrentOptions(&log);
649bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#if SK_SUPPORT_GPU
650c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            if (Benchmark::kGPU_Backend == targets[j]->config.backend) {
651bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio                fill_gpu_options(&log, targets[j]->gl);
652bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio            }
653bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#endif
65460317d0ffb5053df7b08a627d6decd11b684e80dmtklein            log.timer("min_ms",    stats.min);
65560317d0ffb5053df7b08a627d6decd11b684e80dmtklein            log.timer("median_ms", stats.median);
65660317d0ffb5053df7b08a627d6decd11b684e80dmtklein            log.timer("mean_ms",   stats.mean);
65760317d0ffb5053df7b08a627d6decd11b684e80dmtklein            log.timer("max_ms",    stats.max);
65860317d0ffb5053df7b08a627d6decd11b684e80dmtklein            log.timer("stddev_ms", sqrt(stats.var));
65960317d0ffb5053df7b08a627d6decd11b684e80dmtklein
6606eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kAutoTuneLoops != FLAGS_loops) {
661a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                if (targets.count() == 1) {
662a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
663a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                }
664a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                SkDebugf("%s\t%s\n", bench->getName(), config);
665a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            } else if (FLAGS_verbose) {
666f372321de3d4183de5b9ca436e677e471e358f31mtklein                for (int i = 0; i < FLAGS_samples; i++) {
66755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                    SkDebugf("%s  ", HUMANIZE(samples[i]));
668f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
669f372321de3d4183de5b9ca436e677e471e358f31mtklein                SkDebugf("%s\n", bench->getName());
670f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else if (FLAGS_quiet) {
671bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                if (targets.count() == 1) {
672f372321de3d4183de5b9ca436e677e471e358f31mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
673f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
67455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getName(), config);
675f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else {
676f372321de3d4183de5b9ca436e677e471e358f31mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
677afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein                SkDebugf("%4dM\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n"
678afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein                        , sk_tools::getMaxResidentSetSizeMB()
679f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , loops
68055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.min)
68155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.median)
68255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.mean)
68355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.max)
684f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , stddev_percent
6855d9d10e8217d2138b5514a4d4216f95373240942mtklein                        , stats.plot.c_str()
686f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , config
687bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                        , bench->getName()
688f372321de3d4183de5b9ca436e677e471e358f31mtklein                        );
689f372321de3d4183de5b9ca436e677e471e358f31mtklein            }
690f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
691bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        targets.deleteAll();
6923944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein
6933944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein    #if SK_SUPPORT_GPU
6942354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        if (FLAGS_abandonGpuContext) {
69569a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski            gGrFactory->abandonContexts();
6962354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        }
6972354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
69869a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski            gGrFactory->destroyContexts();
6993944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein        }
7003944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein    #endif
701f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
702f372321de3d4183de5b9ca436e677e471e358f31mtklein
703f372321de3d4183de5b9ca436e677e471e358f31mtklein    return 0;
704f372321de3d4183de5b9ca436e677e471e358f31mtklein}
705f372321de3d4183de5b9ca436e677e471e358f31mtklein
706f372321de3d4183de5b9ca436e677e471e358f31mtklein#if !defined SK_BUILD_FOR_IOS
70717f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint main(int argc, char** argv) {
70817f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark    SkCommandLineFlags::Parse(argc, argv);
70917f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark    return nanobench_main();
710f372321de3d4183de5b9ca436e677e471e358f31mtklein}
711f372321de3d4183de5b9ca436e677e471e358f31mtklein#endif
712