Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright 2013 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include "BenchTimer.h" | |
| 9 #include "PictureBenchmark.h" | |
| 10 #include "PictureRenderer.h" | |
| 11 #include "PictureRenderingFlags.h" | |
| 12 #include "SkCommandLineFlags.h" | |
| 13 #include "SkForceLinking.h" | |
| 14 #include "SkStream.h" | |
| 15 #include "SkString.h" | |
| 16 #include "SkGraphics.h" | |
| 17 #include "TimerData.h" | |
| 18 | |
| 19 | |
| 20 __SK_FORCE_IMAGE_DECODER_LINKING; | |
| 21 | |
| 22 static const int kNumRecordings = 10; | |
| 23 static const int kNumPlaybacks = 1; | |
| 24 | |
| 25 static const int gTileDimensions[2] = {128, 128}; | |
| 26 | |
| 27 enum BenchmarkType { | |
| 28 kNormal_BenchmarkType = 0, | |
| 29 kRTree_BenchmarkType, | |
| 30 }; | |
| 31 | |
| 32 // Defined in PictureRenderingFlags.cpp | |
| 33 extern bool lazy_decode_bitmap(const void* buffer, size_t size, SkBitmap* bitmap ); | |
| 34 | |
| 35 static SkPicture* pic_from_path(const char path[]) { | |
| 36 SkFILEStream stream(path); | |
| 37 if (!stream.isValid()) { | |
| 38 SkDebugf("-- Can't open '%s'\n", path); | |
| 39 return NULL; | |
| 40 } | |
| 41 bool success = false; | |
| 42 SkPicture* pic = SkNEW_ARGS(SkPicture, (&stream, &success, &lazy_decode_bitm ap)); | |
| 43 if (!success) { | |
| 44 SkDebugf("Could not create SkPicture: %s\n", path); | |
| 45 return pic; | |
|
caryclark
2013/06/28 18:09:43
just let it fall through
| |
| 46 } | |
| 47 return pic; | |
| 48 } | |
| 49 | |
| 50 /** | |
| 51 * This function is the sink to which all work ends up going. | |
| 52 * Renders the picture into the renderer. It may or may not use an RTree. | |
| 53 * The renderer is chosen upstream. If we want to measure recording, we will | |
| 54 * use a RecordPictureRenderer. If we want to measure rendering, we eill use a | |
| 55 * TiledPictureRenderer. | |
| 56 */ | |
| 57 static void do_benchmark_work(sk_tools::PictureRenderer* renderer, | |
| 58 int benchmarkType, const SkString *path, SkPicture* pic, | |
| 59 const int numRepeats, const char *msg) { | |
| 60 SkASSERT(NULL != pic); | |
| 61 | |
| 62 SkString msgPrefix; | |
| 63 | |
| 64 switch (benchmarkType){ | |
| 65 case kNormal_BenchmarkType: | |
| 66 msgPrefix.printf("Normal"); | |
| 67 renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBox HierarchyType); | |
| 68 break; | |
| 69 case kRTree_BenchmarkType: | |
| 70 msgPrefix.printf("RTree"); | |
| 71 renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kRTree_BBo xHierarchyType); | |
| 72 break; | |
| 73 } | |
| 74 | |
| 75 renderer->init(pic); | |
| 76 | |
| 77 SkDebugf("%s %s %s %d times...\n", msgPrefix.c_str(), msg, path->c_str(), nu mRepeats); | |
| 78 for(int i = 0; i < numRepeats; ++i) { | |
|
caryclark
2013/06/28 18:09:43
space after for
| |
| 79 renderer->setup(); | |
| 80 bool result = renderer->render(path); | |
| 81 if(!result) { | |
|
caryclark
2013/06/28 18:09:43
space after if
| |
| 82 SkDebugf("Error recording.\n"); | |
| 83 } | |
| 84 } | |
| 85 renderer->end(); | |
| 86 } | |
| 87 | |
| 88 /** | |
| 89 * Call do_benchmark_work with a tiled renderer using the default tile dimension s. | |
| 90 */ | |
| 91 static void benchmark_playback(int benchmarkType, const SkString* path, SkPictur e* pic) { | |
| 92 SkAutoTUnref<sk_tools::TiledPictureRenderer> renderer(SkNEW(sk_tools::TiledP ictureRenderer)); | |
|
caryclark
2013/06/28 18:09:43
Since this just lives on the stack, do you need to
sglez
2013/07/01 15:34:38
Changed it to live on the stack.
| |
| 93 SkASSERT(NULL != renderer); | |
| 94 | |
| 95 renderer->setTileWidth(gTileDimensions[0]); | |
| 96 renderer->setTileHeight(gTileDimensions[1]); | |
| 97 | |
| 98 do_benchmark_work(renderer, benchmarkType, path, pic, kNumPlaybacks, "tiled playback"); | |
| 99 } | |
| 100 | |
| 101 /** | |
| 102 * Call do_benchmark_work with a RecordPictureRenderer. | |
| 103 */ | |
| 104 static void benchmark_recording(int benchmarkType, const SkString* path, SkPictu re* pic) { | |
| 105 SkAutoTUnref<sk_tools::PictureRenderer> renderer(SkNEW(sk_tools::RecordPictu reRenderer)); | |
| 106 SkASSERT(NULL != renderer); | |
| 107 | |
| 108 do_benchmark_work(renderer, benchmarkType, path, pic, kNumRecordings, "recor ding"); | |
| 109 } | |
| 110 | |
| 111 /** | |
| 112 * Returns a SkScalar representing CPU time for a TimerData. | |
| 113 * As a side effect, it spits the timer result to stdout. | |
| 114 */ | |
| 115 static SkScalar get_data_result(TimerData &timerData, const char *configName) { | |
| 116 const SkString timerResult = timerData.getResult( | |
| 117 /*logPerIter=*/false, /*printMin=*/false, /*repeatDraw*/1, | |
| 118 /*configName*/configName, | |
| 119 /*showWallTime=*/false, /*showTruncatedWallTime=*/false, /*showCpuTi me=*/true, | |
| 120 /*showTruncatedCpuTime=*/false, /*showGpuTime=*/false | |
|
caryclark
2013/06/28 18:09:43
Good documentation, if a little hard to read. Use
| |
| 121 ); | |
| 122 const char findStr[] = "= "; | |
| 123 int pos = timerResult.find(findStr); | |
|
caryclark
2013/06/28 18:09:43
error check if find fails?
| |
| 124 SkDebugf("%s\n", timerResult.c_str()); | |
|
caryclark
2013/06/28 18:09:43
probably should put debug before find in case find
| |
| 125 const SkScalar cpuTime = atof(timerResult.c_str() + pos + sizeof(findStr) - 1); | |
|
caryclark
2013/06/28 18:09:43
const doesn't add any information here
| |
| 126 return cpuTime; | |
|
caryclark
2013/06/28 18:09:43
error check atof ?
| |
| 127 } | |
| 128 | |
| 129 static const SkString perIterTimeFormat = SkString("%f"); | |
|
caryclark
2013/06/28 18:09:43
... perIterTimeFormat("%f");
etc.
| |
| 130 static const SkString normalTimeFormat = SkString("%f"); | |
| 131 | |
| 132 /** | |
| 133 * Takes argc,argv along with one of the benchmark functions defined above. | |
| 134 * Will loop along all skp files and perform a measurment; then it will return | |
| 135 * that measurement. | |
| 136 */ | |
| 137 TimerData benchmark_loop( | |
| 138 int argc, | |
| 139 char **argv, | |
| 140 void (*func)(int, const SkString*, SkPicture*), | |
| 141 int benchmarkType) { | |
| 142 TimerData timerData(perIterTimeFormat, normalTimeFormat); | |
| 143 for(int index = 1; index < argc; ++index) { | |
|
caryclark
2013/06/28 18:09:43
space after for
| |
| 144 BenchTimer timer; | |
| 145 const SkString path = SkString(argv[index]); | |
|
caryclark
2013/06/28 18:09:43
path(argv[index])
| |
| 146 timer.start(); | |
| 147 SkAutoTUnref<SkPicture> pic(pic_from_path(argv[index])); | |
|
caryclark
2013/06/28 18:09:43
no auto unref required, I don't think, e.g.
SkPic
sglez
2013/07/01 15:34:38
pic_from_path was returning a pointer. I modified
| |
| 148 func(benchmarkType, &path, pic); | |
| 149 timer.end(); | |
| 150 timerData.appendTimes(&timer, index == argc - 1); | |
| 151 } | |
| 152 return timerData; | |
| 153 } | |
| 154 | |
| 155 int tool_main(int argc, char** argv); | |
|
caryclark
2013/06/28 18:09:43
is this seen by someone external to this file, i.e
sglez
2013/07/01 15:34:38
I was following the crowd. Everyone defines tool_m
| |
| 156 int tool_main(int argc, char** argv) { | |
| 157 SkAutoGraphics ag; | |
| 158 SkString usage; | |
| 159 usage.printf("Usage: filename [filename]*\n"); | |
| 160 | |
| 161 if (argc < 2) { | |
| 162 SkDebugf("%s\n", usage.c_str()); | |
| 163 } | |
| 164 | |
| 165 TimerData normalRecordData = | |
| 166 benchmark_loop(argc, argv, benchmark_recording, kNormal_BenchmarkType); | |
| 167 TimerData rtreeRecordData = | |
| 168 benchmark_loop(argc, argv, benchmark_recording, kRTree_BenchmarkType); | |
| 169 TimerData normalPlaybackData = | |
| 170 benchmark_loop(argc, argv, benchmark_playback, kNormal_BenchmarkType); | |
| 171 TimerData rtreePlaybackData = | |
| 172 benchmark_loop(argc, argv, benchmark_playback, kRTree_BenchmarkType); | |
| 173 | |
| 174 const SkScalar normalRecordResult = get_data_result(normalRecordData, "norma l_record"); | |
| 175 const SkScalar rtreeRecordResult = get_data_result(rtreeRecordData, "rtree_r ecord"); | |
| 176 const SkScalar normalPlaybackResult = get_data_result(normalPlaybackData, "n ormal_playback"); | |
| 177 const SkScalar rtreePlaybackResult = get_data_result(rtreePlaybackData, "rtr ee_playback"); | |
|
caryclark
2013/06/28 18:09:43
not sure const adds any value here
| |
| 178 | |
| 179 SkASSERT(normalRecordResult != 0 && normalPlaybackResult != 0); | |
| 180 SkDebugf("Recording: Relative difference: %.4f\n", rtreeRecordResult / norma lRecordResult); | |
| 181 SkDebugf("Playback: Relative difference: %.4f\n", rtreePlaybackResult / nor malPlaybackResult); | |
| 182 | |
| 183 SkScalar times = | |
| 184 (kNumPlaybacks * (normalRecordResult - rtreeRecordResult)) / | |
| 185 (kNumRecordings * (rtreePlaybackResult - normalPlaybackResult)); | |
| 186 | |
| 187 SkDebugf("Number of playback repetitions for RTree to be worth it: %d (ratio : %.4f)\n", | |
| 188 SkScalarCeilToInt(times), times); | |
| 189 | |
| 190 return 0; | |
| 191 } | |
| 192 #undef BENCHMARK_LOOP | |
| 193 | |
| 194 int main(int argc, char** argv) { | |
| 195 return tool_main(argc, argv); | |
| 196 } | |
| 197 | |
| OLD | NEW |