bbh_shootout.cpp revision 0817fb6e1eaa4da6d915f3b9e1201db524a4aad5
1d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org/* 2d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org * Copyright 2013 Google Inc. 3d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org * 4d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 5d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org * found in the LICENSE file. 6d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org */ 7d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 8d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "BenchTimer.h" 9d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "LazyDecodeBitmap.h" 10d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "PictureBenchmark.h" 11d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "PictureRenderer.h" 12d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "SkBenchmark.h" 13d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "SkForceLinking.h" 14d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "SkGraphics.h" 15d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "SkStream.h" 16d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "SkString.h" 17d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org#include "TimerData.h" 18d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 19d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic const int kNumNormalRecordings = SkBENCHLOOP(10); 20d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic const int kNumRTreeRecordings = SkBENCHLOOP(10); 21d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic const int kNumPlaybacks = SkBENCHLOOP(4); 22d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic const size_t kNumBaseBenchmarks = 3; 23d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic const size_t kNumTileSizes = 3; 24d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic const size_t kNumBbhPlaybackBenchmarks = 3; 25d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic const size_t kNumBenchmarks = kNumBaseBenchmarks + kNumBbhPlaybackBenchmarks; 26d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 27d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgenum BenchmarkType { 28d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org kNormal_BenchmarkType = 0, 29d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org kRTree_BenchmarkType, 30d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org}; 31d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 32d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstruct Histogram { 33d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org Histogram() { 34d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org // Make fCpuTime negative so that we don't mess with stats: 35d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org fCpuTime = SkIntToScalar(-1); 36d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 37d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkScalar fCpuTime; 38d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkString fPath; 39d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org}; 40d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 41d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgtypedef void (*BenchmarkFunction) 42992c7b03ef7914a18bfd78e965b0b4c99a5f5672Cary Clark (BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*); 43d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 44d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org// Defined below. 45d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic void benchmark_playback( 46d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*); 47d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic void benchmark_recording( 48d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org BenchmarkType, const SkISize&, const SkString&, SkPicture*, BenchTimer*); 49d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 50d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org/** 51d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org * Acts as a POD containing information needed to run a benchmark. 52d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org * Provides static methods to poll benchmark info from an index. 53d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org */ 54d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstruct BenchmarkControl { 55d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkISize fTileSize; 56d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org BenchmarkType fType; 57d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org BenchmarkFunction fFunction; 58eb9a46cbbb475e862a084aa2224ec18d4ac5e95breed@google.com SkString fName; 59d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 60d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org /** 61d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org * Will construct a BenchmarkControl instance from an index between 0 an kNumBenchmarks. 62d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org */ 63d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org static BenchmarkControl Make(size_t i) { 64d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkASSERT(kNumBenchmarks > i); 65d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org BenchmarkControl benchControl; 66d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org benchControl.fTileSize = getTileSize(i); 67d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org benchControl.fType = getBenchmarkType(i); 68d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org benchControl.fFunction = getBenchmarkFunc(i); 69d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org benchControl.fName = getBenchmarkName(i); 70d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return benchControl; 71d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 72d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 73d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org enum BaseBenchmarks { 74d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org kNormalRecord = 0, 75d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org kRTreeRecord, 76d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org kNormalPlayback, 77eb9a46cbbb475e862a084aa2224ec18d4ac5e95breed@google.com }; 78d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 79d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org static SkISize fTileSizes[kNumTileSizes]; 80d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 81d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org static SkISize getTileSize(size_t i) { 82d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org // Two of the base benchmarks don't need a tile size. But to maintain simplicity 83d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org // down the pipeline we have to let a couple of values unused. 84d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org if (i < kNumBaseBenchmarks) { 85d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return SkISize::Make(256, 256); 86d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 87d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org if (i >= kNumBaseBenchmarks && i < kNumBenchmarks) { 88d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return fTileSizes[i - kNumBaseBenchmarks]; 89d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 90d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkASSERT(0); 91d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return SkISize::Make(0, 0); 92d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 93d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 94d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org static BenchmarkType getBenchmarkType(size_t i) { 95d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org if (i < kNumBaseBenchmarks) { 96d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org switch (i) { 97d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org case kNormalRecord: 98d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return kNormal_BenchmarkType; 99d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org case kNormalPlayback: 100d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return kNormal_BenchmarkType; 101d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org case kRTreeRecord: 102d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return kRTree_BenchmarkType; 103d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 104d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 105d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org if (i < kNumBenchmarks) { 106d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return kRTree_BenchmarkType; 107d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 108d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkASSERT(0); 109d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return kRTree_BenchmarkType; 110d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 111d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 112d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org static BenchmarkFunction getBenchmarkFunc(size_t i) { 113d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org // Base functions. 114d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org switch (i) { 115d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org case kNormalRecord: 116d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return benchmark_recording; 117d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org case kNormalPlayback: 118d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return benchmark_playback; 119a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org case kRTreeRecord: 120d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return benchmark_recording; 121d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 122d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org // RTree playbacks 123d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org if (i < kNumBenchmarks) { 124d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return benchmark_playback; 125d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 126d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkASSERT(0); 127d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return NULL; 128d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 129d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 130d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org static SkString getBenchmarkName(size_t i) { 131d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org // Base benchmark names 132d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org switch (i) { 133d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org case kNormalRecord: 134d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return SkString("normal_recording"); 135d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org case kNormalPlayback: 136d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return SkString("normal_playback"); 137cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org case kRTreeRecord: 138cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org return SkString("rtree_recording"); 139cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org } 140cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org // RTree benchmark names. 141cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org if (i < kNumBenchmarks) { 142cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org SkASSERT(i >= kNumBaseBenchmarks); 143d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkString name; 144d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org name.printf("rtree_playback_%dx%d", 145d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org fTileSizes[i - kNumBaseBenchmarks].fWidth, 146d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org fTileSizes[i - kNumBaseBenchmarks].fHeight); 147d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return name; 148d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 149d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } else { 150d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkASSERT(0); 151d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 152d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return SkString(""); 153d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 154d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 155d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org}; 156d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 157d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgSkISize BenchmarkControl::fTileSizes[kNumTileSizes] = { 158d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkISize::Make(256, 256), 159d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkISize::Make(512, 512), 160d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkISize::Make(1024, 1024), 161d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org}; 162d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 163d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.orgstatic SkPicture* pic_from_path(const char path[]) { 164d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkFILEStream stream(path); 165d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org if (!stream.isValid()) { 166d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org SkDebugf("-- Can't open '%s'\n", path); 167d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return NULL; 168d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org } 169d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org return SkPicture::CreateFromStream(&stream, &sk_tools::LazyDecodeBitmap); 170d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org} 171d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org 172d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org/** 173d8f82a4c44b844fed98d3ecc0072e0626b06bb37senorblanco@chromium.org * This function is the sink to which all work ends up going. 174 * Renders the picture into the renderer. It may or may not use an RTree. 175 * The renderer is chosen upstream. If we want to measure recording, we will 176 * use a RecordPictureRenderer. If we want to measure rendering, we eill use a 177 * TiledPictureRenderer. 178 */ 179static void do_benchmark_work(sk_tools::PictureRenderer* renderer, 180 int benchmarkType, const SkString& path, SkPicture* pic, 181 const int numRepeats, const char *msg, BenchTimer* timer) { 182 SkString msgPrefix; 183 184 switch (benchmarkType){ 185 case kNormal_BenchmarkType: 186 msgPrefix.set("Normal"); 187 renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBoxHierarchyType); 188 break; 189 case kRTree_BenchmarkType: 190 msgPrefix.set("RTree"); 191 renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kRTree_BBoxHierarchyType); 192 break; 193 default: 194 SkASSERT(0); 195 break; 196 } 197 198 renderer->init(pic); 199 200 /** 201 * If the renderer is not tiled, assume we are measuring recording. 202 */ 203 bool isPlayback = (NULL != renderer->getTiledRenderer()); 204 205 SkDebugf("%s %s %s %d times...\n", msgPrefix.c_str(), msg, path.c_str(), numRepeats); 206 for (int i = 0; i < numRepeats; ++i) { 207 renderer->setup(); 208 // Render once to fill caches. 209 renderer->render(NULL); 210 // Render again to measure 211 timer->start(); 212 bool result = renderer->render(NULL); 213 timer->end(); 214 // We only care about a false result on playback. RecordPictureRenderer::render will always 215 // return false because we are passing a NULL file name on purpose; which is fine. 216 if(isPlayback && !result) { 217 SkDebugf("Error rendering during playback.\n"); 218 } 219 } 220 renderer->end(); 221} 222 223/** 224 * Call do_benchmark_work with a tiled renderer using the default tile dimensions. 225 */ 226static void benchmark_playback( 227 BenchmarkType benchmarkType, const SkISize& tileSize, 228 const SkString& path, SkPicture* pic, BenchTimer* timer) { 229 sk_tools::TiledPictureRenderer renderer; 230 231 SkString message("tiled_playback"); 232 message.appendf("_%dx%d", tileSize.fWidth, tileSize.fHeight); 233 do_benchmark_work(&renderer, benchmarkType, 234 path, pic, kNumPlaybacks, message.c_str(), timer); 235} 236 237/** 238 * Call do_benchmark_work with a RecordPictureRenderer. 239 */ 240static void benchmark_recording( 241 BenchmarkType benchmarkType, const SkISize& tileSize, 242 const SkString& path, SkPicture* pic, BenchTimer* timer) { 243 sk_tools::RecordPictureRenderer renderer; 244 int numRecordings = 0; 245 switch(benchmarkType) { 246 case kRTree_BenchmarkType: 247 numRecordings = kNumRTreeRecordings; 248 break; 249 case kNormal_BenchmarkType: 250 numRecordings = kNumNormalRecordings; 251 break; 252 } 253 do_benchmark_work(&renderer, benchmarkType, path, pic, numRecordings, "recording", timer); 254} 255 256/** 257 * Takes argc,argv along with one of the benchmark functions defined above. 258 * Will loop along all skp files and perform measurments. 259 * 260 * Returns a SkScalar representing CPU time taken during benchmark. 261 * As a side effect, it spits the timer result to stdout. 262 * Will return -1.0 on error. 263 */ 264static bool benchmark_loop( 265 int argc, 266 char **argv, 267 const BenchmarkControl& benchControl, 268 Histogram* histogram) { 269 270 static const SkString timeFormat("%f"); 271 TimerData timerData(timeFormat, timeFormat); 272 for (int index = 1; index < argc; ++index) { 273 BenchTimer timer; 274 SkString path(argv[index]); 275 SkAutoTUnref<SkPicture> pic(pic_from_path(path.c_str())); 276 if (NULL == pic) { 277 SkDebugf("Couldn't create picture. Ignoring path: %s\n", path.c_str()); 278 continue; 279 } 280 benchControl.fFunction(benchControl.fType, benchControl.fTileSize, path, pic, &timer); 281 timerData.appendTimes(&timer, argc - 1 == index); 282 283 histogram[index - 1].fPath = path; 284 histogram[index - 1].fCpuTime = SkDoubleToScalar(timer.fCpu); 285 } 286 287 const SkString timerResult = timerData.getResult( 288 /*logPerIter = */ false, 289 /*printMin = */ false, 290 /*repeatDraw = */ 1, 291 /*configName = */ benchControl.fName.c_str(), 292 /*showWallTime = */ false, 293 /*showTruncatedWallTime = */ false, 294 /*showCpuTime = */ true, 295 /*showTruncatedCpuTime = */ false, 296 /*showGpuTime = */ false); 297 298 const char findStr[] = "= "; 299 int pos = timerResult.find(findStr); 300 if (-1 == pos) { 301 SkDebugf("Unexpected output from TimerData::getResult(...). Unable to parse."); 302 return false; 303 } 304 305 SkScalar cpuTime = SkDoubleToScalar(atof(timerResult.c_str() + pos + sizeof(findStr) - 1)); 306 if (cpuTime == 0) { // atof returns 0.0 on error. 307 SkDebugf("Unable to read value from timer result.\n"); 308 return false; 309 } 310 return true; 311} 312 313int tool_main(int argc, char** argv); 314int tool_main(int argc, char** argv) { 315 SkAutoGraphics ag; 316 SkString usage; 317 usage.printf("Usage: filename [filename]*\n"); 318 319 if (argc < 2) { 320 SkDebugf("%s\n", usage.c_str()); 321 return -1; 322 } 323 324 Histogram histograms[argc - 1][kNumBenchmarks]; 325 326 for (size_t i = 0; i < kNumBenchmarks; ++i) { 327 bool success = benchmark_loop( 328 argc, argv, 329 BenchmarkControl::Make(i), 330 histograms[i]); 331 if (!success) { 332 SkDebugf("benchmark_loop failed at index %d", i); 333 } 334 } 335 336 // Output gnuplot readable histogram data.. 337 const char* pbTitle = "bbh_shootout_playback.dat"; 338 const char* recTitle = "bbh_shootout_record.dat"; 339 SkFILEWStream playbackOut(pbTitle); 340 SkFILEWStream recordOut(recTitle); 341 recordOut.writeText("# "); 342 playbackOut.writeText("# "); 343 for (size_t i = 0; i < kNumBenchmarks; ++i) { 344 SkString out; 345 out.printf("%s ", BenchmarkControl::getBenchmarkName(i).c_str()); 346 if (BenchmarkControl::getBenchmarkFunc(i) == &benchmark_recording) { 347 recordOut.writeText(out.c_str()); 348 } 349 if (BenchmarkControl::getBenchmarkFunc(i) == &benchmark_playback) { 350 playbackOut.writeText(out.c_str()); 351 } 352 } 353 recordOut.writeText("\n"); 354 playbackOut.writeText("\n"); 355 356 for (int i = 0; i < argc - 1; ++i) { 357 SkString pbLine; 358 SkString recLine; 359 // ==== Write record info 360 recLine.printf("%d ", i); 361 recLine.appendf("%f ", histograms[0][i].fCpuTime); // Append normal_record time 362 recLine.appendf("%f", histograms[1][i].fCpuTime); // Append rtree_record time 363 364 // ==== Write playback info 365 pbLine.printf("%d ", i); 366 pbLine.appendf("%f ", histograms[2][i].fCpuTime); // Start with normal playback time. 367 // Append all playback benchmark times. 368 for (size_t j = kNumBbhPlaybackBenchmarks; j < kNumBenchmarks; ++j) { 369 pbLine.appendf("%f ", histograms[j][i].fCpuTime); 370 } 371 pbLine.remove(pbLine.size() - 1, 1); // Remove trailing space from line. 372 pbLine.appendf("\n"); 373 recLine.appendf("\n"); 374 playbackOut.writeText(pbLine.c_str()); 375 recordOut.writeText(recLine.c_str()); 376 } 377 SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle); 378 379 return 0; 380} 381 382#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 383int main(int argc, char** argv) { 384 return tool_main(argc, argv); 385} 386#endif 387 388 389