nanobench.cpp revision dc5bbab138bfffc85d6ba525d990aad09c322ff6
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"
15fd731ce804cd3223318f3feee2c98404890b65f2mtklein#include "RecordingBench.h"
1692007583e43115998412ac8b0a06cc2780eb025cmtklein#include "SKPBench.h"
17f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Stats.h"
18f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "Timer.h"
19f372321de3d4183de5b9ca436e677e471e358f31mtklein
202084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkBBHFactory.h"
21f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkCanvas.h"
2217f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark#include "SkCommonFlags.h"
23f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkForceLinking.h"
24f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkGraphics.h"
252084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkOSFile.h"
262084050a33ae139d0fe9bb680f7905f91139a39fmtklein#include "SkPictureRecorder.h"
27f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkString.h"
28f372321de3d4183de5b9ca436e677e471e358f31mtklein#include "SkSurface.h"
29f372321de3d4183de5b9ca436e677e471e358f31mtklein
30bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
31bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    #include "gl/GrGLDefines.h"
32bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    #include "GrContextFactory.h"
3369a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    SkAutoTDelete<GrContextFactory> gGrFactory;
34bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
35bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
36f372321de3d4183de5b9ca436e677e471e358f31mtklein__SK_FORCE_IMAGE_DECODER_LINKING;
37f372321de3d4183de5b9ca436e677e471e358f31mtklein
386eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic const int kAutoTuneLoops = -1;
396eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
40b511042bb07a6a289b0d1146cb57f6e8b80580d6mtkleinstatic const int kDefaultLoops =
416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon#ifdef SK_DEBUG
426eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    1;
43a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#else
446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    kAutoTuneLoops;
45a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein#endif
46a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic SkString loops_help_txt() {
486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString help;
496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    help.printf("Number of times to run each bench. Set this to %d to auto-"
506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                "tune for each bench. Timings are only reported when auto-tuning.",
516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                kAutoTuneLoops);
526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return help;
536eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
546eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonDEFINE_int32(loops, kDefaultLoops, loops_help_txt().c_str());
566eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
57f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(samples, 10, "Number of samples to measure for each bench.");
58f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_int32(overheadLoops, 100000, "Loops to estimate timer overhead.");
59f372321de3d4183de5b9ca436e677e471e358f31mtkleinDEFINE_double(overheadGoal, 0.0001,
60f372321de3d4183de5b9ca436e677e471e358f31mtklein              "Loop until timer overhead is at most this fraction of our measurments.");
61bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_double(gpuMs, 5, "Target bench time in millseconds for GPU.");
62bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinDEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allows to lag.");
6312b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevskiDEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
6412b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski                                          "software path rendering.");
65f372321de3d4183de5b9ca436e677e471e358f31mtklein
6660317d0ffb5053df7b08a627d6decd11b684e80dmtkleinDEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
6755b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxCalibrationAttempts, 3,
6855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein             "Try up to this many times to guess loops for a bench, or skip the bench.");
6955b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinDEFINE_int32(maxLoops, 1000000, "Never run a bench more times than this.");
7092007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(clip, "0,0,1000,1000", "Clip for SKPs.");
7192007583e43115998412ac8b0a06cc2780eb025cmtkleinDEFINE_string(scales, "1.0", "Space-separated scales for SKPs.");
722084050a33ae139d0fe9bb680f7905f91139a39fmtkleinDEFINE_bool(bbh, true, "Build a BBH for SKPs?");
7392007583e43115998412ac8b0a06cc2780eb025cmtklein
74f372321de3d4183de5b9ca436e677e471e358f31mtkleinstatic SkString humanize(double ms) {
75dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (FLAGS_verbose) return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
76dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (ms > 1e+3)     return SkStringPrintf("%.3gs",  ms/1e3);
77dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (ms < 1e-3)     return SkStringPrintf("%.3gns", ms*1e6);
786238688af0d758660d344ec047243d4efefd6f4dmtklein#ifdef SK_BUILD_FOR_WIN
79dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (ms < 1)        return SkStringPrintf("%.3gus", ms*1e3);
806238688af0d758660d344ec047243d4efefd6f4dmtklein#else
81dc5bbab138bfffc85d6ba525d990aad09c322ff6mtklein    if (ms < 1)        return SkStringPrintf("%.3gµs", ms*1e3);
826238688af0d758660d344ec047243d4efefd6f4dmtklein#endif
83f372321de3d4183de5b9ca436e677e471e358f31mtklein    return SkStringPrintf("%.3gms", ms);
84f372321de3d4183de5b9ca436e677e471e358f31mtklein}
8555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein#define HUMANIZE(ms) humanize(ms).c_str()
86f372321de3d4183de5b9ca436e677e471e358f31mtklein
87bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContextHelper* gl) {
886eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (canvas) {
896eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        canvas->clear(SK_ColorWHITE);
906eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
91f372321de3d4183de5b9ca436e677e471e358f31mtklein    WallTimer timer;
92bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    timer.start();
93bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    if (bench) {
94bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        bench->draw(loops, canvas);
95f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
96f372321de3d4183de5b9ca436e677e471e358f31mtklein    if (canvas) {
97f372321de3d4183de5b9ca436e677e471e358f31mtklein        canvas->flush();
98f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
99bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
100bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    if (gl) {
101bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        SK_GL(*gl, Flush());
102bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        gl->swapBuffers();
103bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
104bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
105bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    timer.end();
106bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return timer.fWall;
107f372321de3d4183de5b9ca436e677e471e358f31mtklein}
108f372321de3d4183de5b9ca436e677e471e358f31mtklein
109bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic double estimate_timer_overhead() {
110bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    double overhead = 0;
111bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_overheadLoops; i++) {
112bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        overhead += time(1, NULL, NULL, NULL);
113bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
114bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return overhead / FLAGS_overheadLoops;
115bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
116f372321de3d4183de5b9ca436e677e471e358f31mtklein
11755b0ffc4861e940d8bcf767ff9abf44ff18545eamtkleinstatic int clamp_loops(int loops) {
11855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops < 1) {
11955b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("ERROR: clamping loops from %d to 1.\n", loops);
12055b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return 1;
12155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
12255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    if (loops > FLAGS_maxLoops) {
12355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        SkDebugf("WARNING: clamping loops from %d to FLAGS_maxLoops, %d.\n", loops, FLAGS_maxLoops);
12455b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        return FLAGS_maxLoops;
12555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    }
12655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    return loops;
12755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein}
12855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein
1296eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic bool write_canvas_png(SkCanvas* canvas, const SkString& filename) {
1306eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (filename.isEmpty()) {
1316eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1326eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
133e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    if (kUnknown_SkColorType == canvas->imageInfo().colorType()) {
1346eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1356eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1366eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkBitmap bmp;
1376eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    bmp.setInfo(canvas->imageInfo());
1386eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!canvas->readPixels(&bmp, 0, 0)) {
1396eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't read canvas pixels.\n");
1406eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1416eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1426eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkString dir = SkOSPath::Dirname(filename.c_str());
1436eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!sk_mkdir(dir.c_str())) {
1446eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't make dir %s.\n", dir.c_str());
1456eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1476eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    SkFILEWStream stream(filename.c_str());
1486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!stream.isValid()) {
1496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't write %s.\n", filename.c_str());
1506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!SkImageEncoder::EncodeStream(&stream, bmp, SkImageEncoder::kPNG_Type, 100)) {
1536eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Can't encode a PNG.\n");
1546eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        return false;
1556eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1566eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    return true;
1576eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon}
1586eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
1596eb03cc06d0bc60da5277a83aa0251a475794b04bsalomonstatic int kFailedLoops = -2;
160bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas, double* samples) {
161bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First figure out approximately how many loops of bench it takes to make overhead negligible.
1622069e220034f09aad2f68b262f395e7c25b3d178mtklein    double bench_plus_overhead = 0.0;
16355b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    int round = 0;
1646eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == FLAGS_loops) {
1656eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        while (bench_plus_overhead < overhead) {
1666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (round++ == FLAGS_maxCalibrationAttempts) {
1676eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkDebugf("WARNING: Can't estimate loops for %s (%s vs. %s); skipping.\n",
168962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                         bench->getUniqueName(), HUMANIZE(bench_plus_overhead), HUMANIZE(overhead));
1696eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                return kFailedLoops;
1706eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
1716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            bench_plus_overhead = time(1, bench, canvas, NULL);
17255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein        }
1732069e220034f09aad2f68b262f395e7c25b3d178mtklein    }
174f372321de3d4183de5b9ca436e677e471e358f31mtklein
175bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Later we'll just start and stop the timer once but loop N times.
176f372321de3d4183de5b9ca436e677e471e358f31mtklein    // We'll pick N to make timer overhead negligible:
177f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
178bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //          overhead
179bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  -------------------------  < FLAGS_overheadGoal
180bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  overhead + N * Bench Time
181f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
182bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // where bench_plus_overhead ≈ overhead + Bench Time.
183f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
184f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Doing some math, we get:
185f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
186bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  (overhead / FLAGS_overheadGoal) - overhead
187bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //  ------------------------------------------  < N
188bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    //       bench_plus_overhead - overhead)
189f372321de3d4183de5b9ca436e677e471e358f31mtklein    //
190f372321de3d4183de5b9ca436e677e471e358f31mtklein    // Luckily, this also works well in practice. :)
1916eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    int loops = FLAGS_loops;
1926eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
1936eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double numer = overhead / FLAGS_overheadGoal - overhead;
1946eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        const double denom = bench_plus_overhead - overhead;
1956eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = (int)ceil(numer / denom);
1966eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
1976eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    loops = clamp_loops(loops);
198bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
199bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_samples; i++) {
200bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        samples[i] = time(loops, bench, canvas, NULL) / loops;
201bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
202bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
203f372321de3d4183de5b9ca436e677e471e358f31mtklein}
204f372321de3d4183de5b9ca436e677e471e358f31mtklein
205bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
206bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic int gpu_bench(SkGLContextHelper* gl,
207bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     Benchmark* bench,
208bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     SkCanvas* canvas,
209bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                     double* samples) {
210c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    gl->makeCurrent();
211bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Make sure we're done with whatever came before.
2129bc86ed0523e154f6f4329f43c15012f930e06d7mtklein    SK_GL(*gl, Finish());
213bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
214bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // First, figure out how many loops it'll take to get a frame up to FLAGS_gpuMs.
2156eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    int loops = FLAGS_loops;
2166eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops == loops) {
2176eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        loops = 1;
218a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        double elapsed = 0;
219a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        do {
220a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            loops *= 2;
221a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // If the GPU lets frames lag at all, we need to make sure we're timing
222a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // _this_ round, not still timing last round.  We force this by looping
223a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            // more times than any reasonable GPU will allow frames to lag.
224a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
225a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                elapsed = time(loops, bench, canvas, gl);
226a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            }
227a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        } while (elapsed < FLAGS_gpuMs);
228a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
229a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // We've overshot at least a little.  Scale back linearly.
230a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
231a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
232a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // Might as well make sure we're not still timing our calibration.
233a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        SK_GL(*gl, Finish());
234a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
23555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    loops = clamp_loops(loops);
236bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
237bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Pretty much the same deal as the calibration: do some warmup to make
238bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // sure we're timing steady-state pipelined frames.
239bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
240bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        time(loops, bench, canvas, gl);
241f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
242bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
243bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    // Now, actually do the timing!
244bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_samples; i++) {
245bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        samples[i] = time(loops, bench, canvas, gl) / loops;
246bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
247bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return loops;
248f372321de3d4183de5b9ca436e677e471e358f31mtklein}
249bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
250bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
251bb6a02823929584231c8e080ee69e7fb1178cbfbmtkleinstatic SkString to_lower(const char* str) {
252bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkString lower(str);
253bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (size_t i = 0; i < lower.size(); i++) {
254bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        lower[i] = tolower(lower[i]);
255bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    }
256bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    return lower;
257bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
258bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
259c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstruct Config {
260c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    const char* name;
261bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    Benchmark::Backend backend;
262c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkColorType color;
263c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkAlphaType alpha;
264c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    int samples;
265c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
266c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    GrContextFactory::GLContextType ctxType;
267c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
268c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    int bogusInt;
269c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
270c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon};
271c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
272c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstruct Target {
273c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    explicit Target(const Config& c) : config(c) {}
274c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    const Config config;
275bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkAutoTDelete<SkSurface> surface;
276bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
277bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkGLContextHelper* gl;
278bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
279bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein};
280f372321de3d4183de5b9ca436e677e471e358f31mtklein
281c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_cpu_config_allowed(const char* name) {
282bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    for (int i = 0; i < FLAGS_config.count(); i++) {
283c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (to_lower(FLAGS_config[i]).equals(name)) {
284c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            return true;
285bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        }
286f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
287c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
288bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein}
289f372321de3d4183de5b9ca436e677e471e358f31mtklein
290c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
291c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic bool is_gpu_config_allowed(const char* name, GrContextFactory::GLContextType ctxType,
292c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                  int sampleCnt) {
293c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!is_cpu_config_allowed(name)) {
294c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return false;
295c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
29669a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski    if (const GrContext* ctx = gGrFactory->get(ctxType)) {
297c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return sampleCnt <= ctx->getMaxSampleCount();
298c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
299c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return false;
300c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
301c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
302c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
303c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
304c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType GrContextFactory::kNative_GLContextType
305c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#else
306c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#define kBogusGLContextType 0
307e714e75c725c987fe682a1f5473224fe3e80380dmtklein#endif
308c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
309c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Append all configs that are enabled and supported.
310c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_configs(SkTDArray<Config>* configs) {
311c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    #define CPU_CONFIG(name, backend, color, alpha)                                               \
312c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (is_cpu_config_allowed(#name)) {                                                       \
313c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = { #name, Benchmark::backend, color, alpha, 0, kBogusGLContextType };  \
314c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                                                \
315f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
316e714e75c725c987fe682a1f5473224fe3e80380dmtklein
31740b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_cpu) {
318c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(nonrendering, kNonRendering_Backend, kUnknown_SkColorType, kUnpremul_SkAlphaType)
319c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(8888, kRaster_Backend, kN32_SkColorType, kPremul_SkAlphaType)
320c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        CPU_CONFIG(565, kRaster_Backend, kRGB_565_SkColorType, kOpaque_SkAlphaType)
32140b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
322f372321de3d4183de5b9ca436e677e471e358f31mtklein
323bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
324c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    #define GPU_CONFIG(name, ctxType, samples)                                   \
325c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (is_gpu_config_allowed(#name, GrContextFactory::ctxType, samples)) {  \
326c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            Config config = {                                                    \
327c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                #name,                                                           \
328c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend,                                         \
329c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kN32_SkColorType,                                                \
330c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                kPremul_SkAlphaType,                                             \
331c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                samples,                                                         \
332c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                GrContextFactory::ctxType };                                     \
333c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            configs->push(config);                                               \
334f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
335e714e75c725c987fe682a1f5473224fe3e80380dmtklein
33640b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    if (FLAGS_gpu) {
337c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(gpu, kNative_GLContextType, 0)
338c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(msaa4, kNative_GLContextType, 4)
339c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(msaa16, kNative_GLContextType, 16)
340c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nvprmsaa4, kNVPR_GLContextType, 4)
341c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nvprmsaa16, kNVPR_GLContextType, 16)
342c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(debug, kDebug_GLContextType, 0)
343c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        GPU_CONFIG(nullgpu, kNull_GLContextType, 0)
3443b4d077fba1ad037536db198608a940c47d91888bsalomon#ifdef SK_ANGLE
3453b4d077fba1ad037536db198608a940c47d91888bsalomon        GPU_CONFIG(angle, kANGLE_GLContextType, 0)
3463b4d077fba1ad037536db198608a940c47d91888bsalomon#endif
34740b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    }
348bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
349f372321de3d4183de5b9ca436e677e471e358f31mtklein}
350f372321de3d4183de5b9ca436e677e471e358f31mtklein
351c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// If bench is enabled for config, returns a Target* for it, otherwise NULL.
352c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic Target* is_enabled(Benchmark* bench, const Config& config) {
353c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (!bench->isSuitableFor(config.backend)) {
354c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return NULL;
355c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
356c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
357e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY,
358e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                                         config.color, config.alpha);
359c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
360c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    Target* target = new Target(config);
361c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
362c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (Benchmark::kRaster_Backend == config.backend) {
363c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        target->surface.reset(SkSurface::NewRaster(info));
364c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
365c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#if SK_SUPPORT_GPU
366c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    else if (Benchmark::kGPU_Backend == config.backend) {
36769a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski        target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.ctxType), info,
368c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                                                         config.samples));
36969a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski        target->gl = gGrFactory->getGLContext(config.ctxType);
370c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
371c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon#endif
372c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
373c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    if (Benchmark::kNonRendering_Backend != config.backend && !target->surface.get()) {
374c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        delete target;
375c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        return NULL;
376c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
377c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    return target;
378c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
379c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
380c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon// Creates targets for a benchmark and a set of configs.
381c2553373ee982b6c7c753e7e5035523bc01a7291bsalomonstatic void create_targets(SkTDArray<Target*>* targets, Benchmark* b,
382c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                           const SkTDArray<Config>& configs) {
383c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    for (int i = 0; i < configs.count(); ++i) {
384c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        if (Target* t = is_enabled(b, configs[i])) {
385c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            targets->push(t);
386c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        }
387e714e75c725c987fe682a1f5473224fe3e80380dmtklein
388c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    }
389c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon}
390c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
391bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#if SK_SUPPORT_GPU
392bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregoriostatic void fill_gpu_options(ResultsWriter* log, SkGLContextHelper* ctx) {
39305c4560ab36447895d510655f927fcf123330497jcgregorio    const GrGLubyte* version;
394bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION));
395bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_VERSION", (const char*)(version));
396bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
397bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER));
398bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_RENDERER", (const char*) version);
399bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
400bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR));
401bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_VENDOR", (const char*) version);
402bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
403bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
404bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
405bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio}
406bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#endif
407bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
408e714e75c725c987fe682a1f5473224fe3e80380dmtkleinclass BenchmarkStream {
409e714e75c725c987fe682a1f5473224fe3e80380dmtkleinpublic:
41092007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream() : fBenches(BenchRegistry::Head())
41192007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fGMs(skiagm::GMRegistry::Head())
412fd731ce804cd3223318f3feee2c98404890b65f2mtklein                      , fCurrentRecording(0)
41392007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentScale(0)
41492007583e43115998412ac8b0a06cc2780eb025cmtklein                      , fCurrentSKP(0) {
41592007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_skps.count(); i++) {
41692007583e43115998412ac8b0a06cc2780eb025cmtklein            if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
41792007583e43115998412ac8b0a06cc2780eb025cmtklein                fSKPs.push_back() = FLAGS_skps[i];
41892007583e43115998412ac8b0a06cc2780eb025cmtklein            } else {
41992007583e43115998412ac8b0a06cc2780eb025cmtklein                SkOSFile::Iter it(FLAGS_skps[i], ".skp");
42092007583e43115998412ac8b0a06cc2780eb025cmtklein                SkString path;
42192007583e43115998412ac8b0a06cc2780eb025cmtklein                while (it.next(&path)) {
42292007583e43115998412ac8b0a06cc2780eb025cmtklein                    fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str());
42392007583e43115998412ac8b0a06cc2780eb025cmtklein                }
42492007583e43115998412ac8b0a06cc2780eb025cmtklein            }
42592007583e43115998412ac8b0a06cc2780eb025cmtklein        }
42692007583e43115998412ac8b0a06cc2780eb025cmtklein
42792007583e43115998412ac8b0a06cc2780eb025cmtklein        if (4 != sscanf(FLAGS_clip[0], "%d,%d,%d,%d",
42892007583e43115998412ac8b0a06cc2780eb025cmtklein                        &fClip.fLeft, &fClip.fTop, &fClip.fRight, &fClip.fBottom)) {
42992007583e43115998412ac8b0a06cc2780eb025cmtklein            SkDebugf("Can't parse %s from --clip as an SkIRect.\n", FLAGS_clip[0]);
43092007583e43115998412ac8b0a06cc2780eb025cmtklein            exit(1);
43192007583e43115998412ac8b0a06cc2780eb025cmtklein        }
43292007583e43115998412ac8b0a06cc2780eb025cmtklein
43392007583e43115998412ac8b0a06cc2780eb025cmtklein        for (int i = 0; i < FLAGS_scales.count(); i++) {
43492007583e43115998412ac8b0a06cc2780eb025cmtklein            if (1 != sscanf(FLAGS_scales[i], "%f", &fScales.push_back())) {
43592007583e43115998412ac8b0a06cc2780eb025cmtklein                SkDebugf("Can't parse %s from --scales as an SkScalar.\n", FLAGS_scales[i]);
43692007583e43115998412ac8b0a06cc2780eb025cmtklein                exit(1);
43792007583e43115998412ac8b0a06cc2780eb025cmtklein            }
43892007583e43115998412ac8b0a06cc2780eb025cmtklein        }
43992007583e43115998412ac8b0a06cc2780eb025cmtklein    }
440e714e75c725c987fe682a1f5473224fe3e80380dmtklein
441fd731ce804cd3223318f3feee2c98404890b65f2mtklein    static bool ReadPicture(const char* path, SkAutoTUnref<SkPicture>* pic) {
442fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Not strictly necessary, as it will be checked again later,
443fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // but helps to avoid a lot of pointless work if we're going to skip it.
444fd731ce804cd3223318f3feee2c98404890b65f2mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, path)) {
445fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
446fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
447fd731ce804cd3223318f3feee2c98404890b65f2mtklein
448fd731ce804cd3223318f3feee2c98404890b65f2mtklein        SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
449fd731ce804cd3223318f3feee2c98404890b65f2mtklein        if (stream.get() == NULL) {
450fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s.\n", path);
451fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
452fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
453fd731ce804cd3223318f3feee2c98404890b65f2mtklein
454963504bd0a8ced7e1177ae136da03a9cc343d886mtklein        pic->reset(SkPicture::CreateFromStream(stream.get()));
455fd731ce804cd3223318f3feee2c98404890b65f2mtklein        if (pic->get() == NULL) {
456fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkDebugf("Could not read %s as an SkPicture.\n", path);
457fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return false;
458fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
459fd731ce804cd3223318f3feee2c98404890b65f2mtklein        return true;
460fd731ce804cd3223318f3feee2c98404890b65f2mtklein    }
461fd731ce804cd3223318f3feee2c98404890b65f2mtklein
46292007583e43115998412ac8b0a06cc2780eb025cmtklein    Benchmark* next() {
463e714e75c725c987fe682a1f5473224fe3e80380dmtklein        if (fBenches) {
464e714e75c725c987fe682a1f5473224fe3e80380dmtklein            Benchmark* bench = fBenches->factory()(NULL);
465e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fBenches = fBenches->next();
46692007583e43115998412ac8b0a06cc2780eb025cmtklein            fSourceType = "bench";
467fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "micro";
468e714e75c725c987fe682a1f5473224fe3e80380dmtklein            return bench;
469e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
47092007583e43115998412ac8b0a06cc2780eb025cmtklein
471e714e75c725c987fe682a1f5473224fe3e80380dmtklein        while (fGMs) {
472e714e75c725c987fe682a1f5473224fe3e80380dmtklein            SkAutoTDelete<skiagm::GM> gm(fGMs->factory()(NULL));
473e714e75c725c987fe682a1f5473224fe3e80380dmtklein            fGMs = fGMs->next();
474e714e75c725c987fe682a1f5473224fe3e80380dmtklein            if (gm->getFlags() & skiagm::GM::kAsBench_Flag) {
47592007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "gm";
476fd731ce804cd3223318f3feee2c98404890b65f2mtklein                fBenchType  = "micro";
477e714e75c725c987fe682a1f5473224fe3e80380dmtklein                return SkNEW_ARGS(GMBench, (gm.detach()));
478e714e75c725c987fe682a1f5473224fe3e80380dmtklein            }
479e714e75c725c987fe682a1f5473224fe3e80380dmtklein        }
48092007583e43115998412ac8b0a06cc2780eb025cmtklein
481fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // First add all .skps as RecordingBenches.
482fd731ce804cd3223318f3feee2c98404890b65f2mtklein        while (fCurrentRecording < fSKPs.count()) {
483fd731ce804cd3223318f3feee2c98404890b65f2mtklein            const SkString& path = fSKPs[fCurrentRecording++];
484fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkAutoTUnref<SkPicture> pic;
485fd731ce804cd3223318f3feee2c98404890b65f2mtklein            if (!ReadPicture(path.c_str(), &pic)) {
486fd731ce804cd3223318f3feee2c98404890b65f2mtklein                continue;
487fd731ce804cd3223318f3feee2c98404890b65f2mtklein            }
488fd731ce804cd3223318f3feee2c98404890b65f2mtklein            SkString name = SkOSPath::Basename(path.c_str());
489fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fSourceType = "skp";
490fd731ce804cd3223318f3feee2c98404890b65f2mtklein            fBenchType  = "recording";
491fd731ce804cd3223318f3feee2c98404890b65f2mtklein            return SkNEW_ARGS(RecordingBench, (name.c_str(), pic.get(), FLAGS_bbh));
492fd731ce804cd3223318f3feee2c98404890b65f2mtklein        }
493fd731ce804cd3223318f3feee2c98404890b65f2mtklein
494fd731ce804cd3223318f3feee2c98404890b65f2mtklein        // Then once each for each scale as SKPBenches (playback).
49592007583e43115998412ac8b0a06cc2780eb025cmtklein        while (fCurrentScale < fScales.count()) {
49692007583e43115998412ac8b0a06cc2780eb025cmtklein            while (fCurrentSKP < fSKPs.count()) {
49792007583e43115998412ac8b0a06cc2780eb025cmtklein                const SkString& path = fSKPs[fCurrentSKP++];
498fd731ce804cd3223318f3feee2c98404890b65f2mtklein                SkAutoTUnref<SkPicture> pic;
499fd731ce804cd3223318f3feee2c98404890b65f2mtklein                if (!ReadPicture(path.c_str(), &pic)) {
50092007583e43115998412ac8b0a06cc2780eb025cmtklein                    continue;
50192007583e43115998412ac8b0a06cc2780eb025cmtklein                }
5022084050a33ae139d0fe9bb680f7905f91139a39fmtklein                if (FLAGS_bbh) {
5032084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    // The SKP we read off disk doesn't have a BBH.  Re-record so it grows one.
5042084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    // Here we use an SkTileGrid with parameters optimized for FLAGS_clip.
5052084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    const SkTileGridFactory::TileGridInfo info = {
5062084050a33ae139d0fe9bb680f7905f91139a39fmtklein                        SkISize::Make(fClip.width(), fClip.height()),  // tile interval
5072084050a33ae139d0fe9bb680f7905f91139a39fmtklein                        SkISize::Make(0,0),                            // margin
5082084050a33ae139d0fe9bb680f7905f91139a39fmtklein                        SkIPoint::Make(fClip.left(), fClip.top()),     // offset
5092084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    };
5102084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    SkTileGridFactory factory(info);
5112084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    SkPictureRecorder recorder;
512c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips                    pic->playback(recorder.beginRecording(pic->cullRect().width(),
513ea65bfa8ded918b908287e3e3474aaf5cbd12feamtklein                                                          pic->cullRect().height(),
514c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips                                                          &factory));
5152084050a33ae139d0fe9bb680f7905f91139a39fmtklein                    pic.reset(recorder.endRecording());
5162084050a33ae139d0fe9bb680f7905f91139a39fmtklein                }
517fd731ce804cd3223318f3feee2c98404890b65f2mtklein                SkString name = SkOSPath::Basename(path.c_str());
51892007583e43115998412ac8b0a06cc2780eb025cmtklein                fSourceType = "skp";
519fd731ce804cd3223318f3feee2c98404890b65f2mtklein                fBenchType  = "playback";
52092007583e43115998412ac8b0a06cc2780eb025cmtklein                return SkNEW_ARGS(SKPBench,
52192007583e43115998412ac8b0a06cc2780eb025cmtklein                        (name.c_str(), pic.get(), fClip, fScales[fCurrentScale]));
52292007583e43115998412ac8b0a06cc2780eb025cmtklein            }
52392007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentSKP = 0;
52492007583e43115998412ac8b0a06cc2780eb025cmtklein            fCurrentScale++;
52592007583e43115998412ac8b0a06cc2780eb025cmtklein        }
52692007583e43115998412ac8b0a06cc2780eb025cmtklein
527e714e75c725c987fe682a1f5473224fe3e80380dmtklein        return NULL;
528e714e75c725c987fe682a1f5473224fe3e80380dmtklein    }
52992007583e43115998412ac8b0a06cc2780eb025cmtklein
53092007583e43115998412ac8b0a06cc2780eb025cmtklein    void fillCurrentOptions(ResultsWriter* log) const {
53192007583e43115998412ac8b0a06cc2780eb025cmtklein        log->configOption("source_type", fSourceType);
532fd731ce804cd3223318f3feee2c98404890b65f2mtklein        log->configOption("bench_type",  fBenchType);
53392007583e43115998412ac8b0a06cc2780eb025cmtklein        if (0 == strcmp(fSourceType, "skp")) {
53492007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("clip",
53592007583e43115998412ac8b0a06cc2780eb025cmtklein                    SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop,
53692007583e43115998412ac8b0a06cc2780eb025cmtklein                                                  fClip.fRight, fClip.fBottom).c_str());
53792007583e43115998412ac8b0a06cc2780eb025cmtklein            log->configOption("scale", SkStringPrintf("%.2g", fScales[fCurrentScale]).c_str());
53892007583e43115998412ac8b0a06cc2780eb025cmtklein        }
53992007583e43115998412ac8b0a06cc2780eb025cmtklein    }
54092007583e43115998412ac8b0a06cc2780eb025cmtklein
541e714e75c725c987fe682a1f5473224fe3e80380dmtkleinprivate:
542e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const BenchRegistry* fBenches;
543e714e75c725c987fe682a1f5473224fe3e80380dmtklein    const skiagm::GMRegistry* fGMs;
54492007583e43115998412ac8b0a06cc2780eb025cmtklein    SkIRect            fClip;
54592007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkScalar> fScales;
54692007583e43115998412ac8b0a06cc2780eb025cmtklein    SkTArray<SkString> fSKPs;
54792007583e43115998412ac8b0a06cc2780eb025cmtklein
548fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fSourceType;  // What we're benching: bench, GM, SKP, ...
549fd731ce804cd3223318f3feee2c98404890b65f2mtklein    const char* fBenchType;   // How we bench it: micro, recording, playback, ...
550fd731ce804cd3223318f3feee2c98404890b65f2mtklein    int fCurrentRecording;
55192007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentScale;
55292007583e43115998412ac8b0a06cc2780eb025cmtklein    int fCurrentSKP;
553e714e75c725c987fe682a1f5473224fe3e80380dmtklein};
554e714e75c725c987fe682a1f5473224fe3e80380dmtklein
55517f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main();
55617f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint nanobench_main() {
557f372321de3d4183de5b9ca436e677e471e358f31mtklein    SetupCrashHandler();
558f372321de3d4183de5b9ca436e677e471e358f31mtklein    SkAutoGraphics ag;
559f372321de3d4183de5b9ca436e677e471e358f31mtklein
56069a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#if SK_SUPPORT_GPU
56112b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    GrContext::Options grContextOpts;
56212b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
56312b3544028e74712c6c095ed3a2e8a78de6b2ed8krajcevski    gGrFactory.reset(SkNEW_ARGS(GrContextFactory, (grContextOpts)));
56469a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski#endif
56569a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski
5666eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
567a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_samples     = 1;
568a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        FLAGS_gpuFrameLag = 0;
569a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    }
570a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
5716eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (!FLAGS_writePath.isEmpty()) {
5726eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Writing files to %s.\n", FLAGS_writePath[0]);
5736eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        if (!sk_mkdir(FLAGS_writePath[0])) {
5746eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            SkDebugf("Could not create %s. Files won't be written.\n", FLAGS_writePath[0]);
5756eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            FLAGS_writePath.set(0, NULL);
5766eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        }
5776eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    }
5786eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
5791915b62637bea20e1471a8a358b22e9e47a4a385mtklein    SkAutoTDelete<ResultsWriter> log(SkNEW(ResultsWriter));
58060317d0ffb5053df7b08a627d6decd11b684e80dmtklein    if (!FLAGS_outResultsFile.isEmpty()) {
5811915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log.reset(SkNEW(NanoJSONResultsWriter(FLAGS_outResultsFile[0])));
58260317d0ffb5053df7b08a627d6decd11b684e80dmtklein    }
583bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio
5841915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_properties.count() % 2) {
5851915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n");
586bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        return 1;
587bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
5881915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_properties.count(); i += 2) {
5891915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->property(FLAGS_properties[i-1], FLAGS_properties[i]);
590bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio    }
59194e51567dd691c3e1e8dfa6005a301d72cecf48emtklein
5921915b62637bea20e1471a8a358b22e9e47a4a385mtklein    if (1 == FLAGS_key.count() % 2) {
5931915b62637bea20e1471a8a358b22e9e47a4a385mtklein        SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
59494e51567dd691c3e1e8dfa6005a301d72cecf48emtklein        return 1;
59594e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
5961915b62637bea20e1471a8a358b22e9e47a4a385mtklein    for (int i = 1; i < FLAGS_key.count(); i += 2) {
5971915b62637bea20e1471a8a358b22e9e47a4a385mtklein        log->key(FLAGS_key[i-1], FLAGS_key[i]);
59894e51567dd691c3e1e8dfa6005a301d72cecf48emtklein    }
59960317d0ffb5053df7b08a627d6decd11b684e80dmtklein
600f372321de3d4183de5b9ca436e677e471e358f31mtklein    const double overhead = estimate_timer_overhead();
60155b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein    SkDebugf("Timer overhead: %s\n", HUMANIZE(overhead));
602912947737a973421f4c58682b6171cb5ee00ad3aMike Klein
603bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein    SkAutoTMalloc<double> samples(FLAGS_samples);
604bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
6056eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon    if (kAutoTuneLoops != FLAGS_loops) {
6066eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon        SkDebugf("Fixed number of loops; times would only be misleading so we won't print them.\n");
607a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein    } else if (FLAGS_verbose) {
608f372321de3d4183de5b9ca436e677e471e358f31mtklein        // No header.
609f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else if (FLAGS_quiet) {
61040b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        SkDebugf("median\tbench\tconfig\n");
611f372321de3d4183de5b9ca436e677e471e358f31mtklein    } else {
6128247ec313d87afcdd4da59b1f2f0d24e0983e359qiankun.miao        SkDebugf("maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tconfig\tbench\n",
6138247ec313d87afcdd4da59b1f2f0d24e0983e359qiankun.miao                 FLAGS_samples, "samples");
614f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
615f372321de3d4183de5b9ca436e677e471e358f31mtklein
616c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    SkTDArray<Config> configs;
617c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon    create_configs(&configs);
618c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon
61992007583e43115998412ac8b0a06cc2780eb025cmtklein    BenchmarkStream benchStream;
62092007583e43115998412ac8b0a06cc2780eb025cmtklein    while (Benchmark* b = benchStream.next()) {
621e714e75c725c987fe682a1f5473224fe3e80380dmtklein        SkAutoTDelete<Benchmark> bench(b);
622962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName())) {
623f372321de3d4183de5b9ca436e677e471e358f31mtklein            continue;
624f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
625f372321de3d4183de5b9ca436e677e471e358f31mtklein
626bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        SkTDArray<Target*> targets;
627c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon        create_targets(&targets, bench.get(), configs);
628f372321de3d4183de5b9ca436e677e471e358f31mtklein
629bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        if (!targets.isEmpty()) {
630962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSize().fY);
631bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio            bench->preDraw();
632bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio        }
633bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        for (int j = 0; j < targets.count(); j++) {
634bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein            SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL;
635c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            const char* config = targets[j]->config.name;
636bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein
637bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein            const int loops =
638bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#if SK_SUPPORT_GPU
639c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon                Benchmark::kGPU_Backend == targets[j]->config.backend
640bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                ? gpu_bench(targets[j]->gl, bench.get(), canvas, samples.get())
641bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                :
642bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein#endif
643bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                 cpu_bench(       overhead, bench.get(), canvas, samples.get());
644f372321de3d4183de5b9ca436e677e471e358f31mtklein
64549f085dddff10473b6ebf832a974288300224e60bsalomon            if (canvas && !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) {
6466eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config);
647962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniqueName());
6486eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                pngFilename.append(".png");
6496eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon                write_canvas_png(canvas, pngFilename);
6506eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            }
6516eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon
6526eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kFailedLoops == loops) {
6532069e220034f09aad2f68b262f395e7c25b3d178mtklein                // Can't be timed.  A warning note has already been printed.
654e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein                continue;
655e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            }
65660317d0ffb5053df7b08a627d6decd11b684e80dmtklein
657e3631364e93ee9164f3ce322778d5a50c33f63a6Mike Klein            Stats stats(samples.get(), FLAGS_samples);
6581915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->config(config);
659962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein            log->configOption("name", bench->getName());
6601915b62637bea20e1471a8a358b22e9e47a4a385mtklein            benchStream.fillCurrentOptions(log.get());
661bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#if SK_SUPPORT_GPU
662c2553373ee982b6c7c753e7e5035523bc01a7291bsalomon            if (Benchmark::kGPU_Backend == targets[j]->config.backend) {
6631915b62637bea20e1471a8a358b22e9e47a4a385mtklein                fill_gpu_options(log.get(), targets[j]->gl);
664bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio            }
665bf5e5237b8f5dc9288d72e90864d6ba8d4bfbb72jcgregorio#endif
6661915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("min_ms",    stats.min);
6671915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("median_ms", stats.median);
6681915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("mean_ms",   stats.mean);
6691915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("max_ms",    stats.max);
6701915b62637bea20e1471a8a358b22e9e47a4a385mtklein            log->timer("stddev_ms", sqrt(stats.var));
67160317d0ffb5053df7b08a627d6decd11b684e80dmtklein
6726eb03cc06d0bc60da5277a83aa0251a475794b04bsalomon            if (kAutoTuneLoops != FLAGS_loops) {
673a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                if (targets.count() == 1) {
674a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
675a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                }
67653d2562006ee371222963750009a706cfd1a94f7mtklein                SkDebugf("%4dM\t%s\t%s\n"
67753d2562006ee371222963750009a706cfd1a94f7mtklein                         , sk_tools::getMaxResidentSetSizeMB()
67853d2562006ee371222963750009a706cfd1a94f7mtklein                         , bench->getUniqueName()
67953d2562006ee371222963750009a706cfd1a94f7mtklein                         , config);
680a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            } else if (FLAGS_verbose) {
681f372321de3d4183de5b9ca436e677e471e358f31mtklein                for (int i = 0; i < FLAGS_samples; i++) {
68255b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                    SkDebugf("%s  ", HUMANIZE(samples[i]));
683f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
684962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                SkDebugf("%s\n", bench->getUniqueName());
685f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else if (FLAGS_quiet) {
686bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein                if (targets.count() == 1) {
687f372321de3d4183de5b9ca436e677e471e358f31mtklein                    config = ""; // Only print the config if we run the same bench on more than one.
688f372321de3d4183de5b9ca436e677e471e358f31mtklein                }
689962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getUniqueName(), config);
690f372321de3d4183de5b9ca436e677e471e358f31mtklein            } else {
691f372321de3d4183de5b9ca436e677e471e358f31mtklein                const double stddev_percent = 100 * sqrt(stats.var) / stats.mean;
692afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein                SkDebugf("%4dM\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n"
693afb4379dbca4d4d3824ace183a7348d24bc1589fmtklein                        , sk_tools::getMaxResidentSetSizeMB()
694f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , loops
69555b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.min)
69655b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.median)
69755b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.mean)
69855b0ffc4861e940d8bcf767ff9abf44ff18545eamtklein                        , HUMANIZE(stats.max)
699f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , stddev_percent
7005d9d10e8217d2138b5514a4d4216f95373240942mtklein                        , stats.plot.c_str()
701f372321de3d4183de5b9ca436e677e471e358f31mtklein                        , config
702962890568ddac03d8eb8467a2e81b6f2b7f046f0mtklein                        , bench->getUniqueName()
703f372321de3d4183de5b9ca436e677e471e358f31mtklein                        );
704f372321de3d4183de5b9ca436e677e471e358f31mtklein            }
705f372321de3d4183de5b9ca436e677e471e358f31mtklein        }
706bb6a02823929584231c8e080ee69e7fb1178cbfbmtklein        targets.deleteAll();
7073944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein
7083944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein    #if SK_SUPPORT_GPU
7092354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        if (FLAGS_abandonGpuContext) {
71069a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski            gGrFactory->abandonContexts();
7112354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        }
7122354f8432a7205571f04f9638a0018fb0b1fb282bsalomon        if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
71369a5560ea5a8d26b120f5158e506a163d32b4a27krajcevski            gGrFactory->destroyContexts();
7143944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein        }
7153944a1d2374d2de8622b0192aa080dba6fb92c76Mike Klein    #endif
716f372321de3d4183de5b9ca436e677e471e358f31mtklein    }
717f372321de3d4183de5b9ca436e677e471e358f31mtklein
718f372321de3d4183de5b9ca436e677e471e358f31mtklein    return 0;
719f372321de3d4183de5b9ca436e677e471e358f31mtklein}
720f372321de3d4183de5b9ca436e677e471e358f31mtklein
721f372321de3d4183de5b9ca436e677e471e358f31mtklein#if !defined SK_BUILD_FOR_IOS
72217f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclarkint main(int argc, char** argv) {
72317f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark    SkCommandLineFlags::Parse(argc, argv);
72417f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark    return nanobench_main();
725f372321de3d4183de5b9ca436e677e471e358f31mtklein}
726f372321de3d4183de5b9ca436e677e471e358f31mtklein#endif
727