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] = {256, 256}; | |
| 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[], bool* success) { | |
| 36 SkFILEStream stream(path); | |
| 37 *success = false; | |
| 38 if (!stream.isValid()) { | |
| 39 SkDebugf("-- Can't open '%s'\n", path); | |
| 40 } | |
| 41 SkPicture pic(&stream, success, &lazy_decode_bitmap); | |
| 42 if (!success) { | |
|
reed1
2013/07/08 12:07:03
Is there a Factory method to create a picture from
sglez
2013/07/08 22:00:34
There is SkPicture::CreateFromStream... it's newer
| |
| 43 SkDebugf("Could not create SkPicture: %s\n", path); | |
| 44 } | |
| 45 return pic; | |
| 46 } | |
| 47 | |
| 48 /** | |
| 49 * This function is the sink to which all work ends up going. | |
| 50 * Renders the picture into the renderer. It may or may not use an RTree. | |
| 51 * The renderer is chosen upstream. If we want to measure recording, we will | |
| 52 * use a RecordPictureRenderer. If we want to measure rendering, we eill use a | |
| 53 * TiledPictureRenderer. | |
| 54 */ | |
| 55 static void do_benchmark_work(sk_tools::PictureRenderer* renderer, | |
| 56 int benchmarkType, const SkString *path, SkPicture* pic, | |
| 57 const int numRepeats, const char *msg) { | |
| 58 SkASSERT(NULL != pic); | |
| 59 | |
| 60 SkString msgPrefix; | |
| 61 | |
| 62 switch (benchmarkType){ | |
| 63 case kNormal_BenchmarkType: | |
| 64 msgPrefix.printf("Normal"); | |
| 65 renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kNone_BBox HierarchyType); | |
| 66 break; | |
| 67 case kRTree_BenchmarkType: | |
| 68 msgPrefix.printf("RTree"); | |
| 69 renderer->setBBoxHierarchyType(sk_tools::PictureRenderer::kRTree_BBo xHierarchyType); | |
| 70 break; | |
| 71 } | |
| 72 | |
| 73 renderer->init(pic); | |
| 74 | |
| 75 SkDebugf("%s %s %s %d times...\n", msgPrefix.c_str(), msg, path->c_str(), nu mRepeats); | |
| 76 for (int i = 0; i < numRepeats; ++i) { | |
| 77 renderer->setup(); | |
| 78 bool result = renderer->render(path); | |
| 79 if(!result) { | |
| 80 SkDebugf("Error recording.\n"); | |
| 81 } | |
| 82 } | |
| 83 renderer->end(); | |
| 84 } | |
| 85 | |
| 86 /** | |
| 87 * Call do_benchmark_work with a tiled renderer using the default tile dimension s. | |
| 88 */ | |
| 89 static void benchmark_playback(int benchmarkType, const SkString* path, SkPictur e* pic) { | |
| 90 sk_tools::TiledPictureRenderer renderer; | |
| 91 | |
| 92 renderer.setTileWidth(gTileDimensions[0]); | |
| 93 renderer.setTileHeight(gTileDimensions[1]); | |
| 94 | |
| 95 do_benchmark_work(&renderer, benchmarkType, path, pic, kNumPlaybacks, "tiled playback"); | |
| 96 } | |
| 97 | |
| 98 /** | |
| 99 * Call do_benchmark_work with a RecordPictureRenderer. | |
| 100 */ | |
| 101 static void benchmark_recording(int benchmarkType, const SkString* path, SkPictu re* pic) { | |
| 102 sk_tools::RecordPictureRenderer renderer; | |
| 103 | |
| 104 do_benchmark_work(&renderer, benchmarkType, path, pic, kNumRecordings, "reco rding"); | |
| 105 } | |
| 106 | |
| 107 /** | |
| 108 * Returns a SkScalar representing CPU time for a TimerData. | |
| 109 * As a side effect, it spits the timer result to stdout. | |
| 110 * Will return -1.0 on error. | |
| 111 */ | |
| 112 static SkScalar get_data_result(TimerData &timerData, const char *configName) { | |
| 113 const SkString timerResult = timerData.getResult( | |
| 114 /*logPerIter = */ false, | |
| 115 /*printMin = */ false, | |
| 116 /*repeatDraw = */ 1, | |
| 117 /*configName = */ configName, | |
| 118 /*showWallTime = */ false, | |
| 119 /*showTruncatedWallTime = */ false, | |
| 120 /*showCpuTime = */ true, | |
| 121 /*showTruncatedCpuTime = */ false, | |
| 122 /*showGpuTime = */ false); | |
| 123 | |
| 124 const char findStr[] = "= "; | |
| 125 int pos = timerResult.find(findStr); | |
| 126 if (-1 == pos) { | |
| 127 SkDebugf("Unexpected output from TimerData::getResult(...). Unable to pa rse."); | |
| 128 return -1.0; | |
| 129 } | |
| 130 SkDebugf("%s\n", timerResult.c_str()); | |
| 131 | |
| 132 SkScalar cpuTime = atof(timerResult.c_str() + pos + sizeof(findStr) - 1); | |
| 133 if (cpuTime == SkIntToScalar(0)) { // atof returns 0.0 on error. | |
| 134 SkDebugf("Unable to read value from timer result.\n"); | |
| 135 return -1.0; | |
| 136 } | |
| 137 return cpuTime; | |
| 138 } | |
| 139 | |
| 140 static const SkString perIterTimeFormat("%f"); | |
| 141 static const SkString normalTimeFormat("%f"); | |
| 142 | |
| 143 /** | |
| 144 * Takes argc,argv along with one of the benchmark functions defined above. | |
| 145 * Will loop along all skp files and perform a measurment; then it will return | |
| 146 * that measurement. | |
| 147 */ | |
| 148 TimerData benchmark_loop( | |
| 149 int argc, | |
| 150 char **argv, | |
| 151 void (*func)(int, const SkString*, SkPicture*), | |
| 152 int benchmarkType) { | |
| 153 TimerData timerData(perIterTimeFormat, normalTimeFormat); | |
| 154 for (int index = 1; index < argc; ++index) { | |
| 155 BenchTimer timer; | |
| 156 SkString path(argv[index]); | |
| 157 timer.start(); | |
| 158 bool success = false; | |
| 159 SkPicture pic = pic_from_path(argv[index], &success); | |
| 160 if (success) { | |
| 161 func(benchmarkType, &path, &pic); | |
| 162 } | |
| 163 timer.end(); | |
| 164 timerData.appendTimes(&timer, index == argc - 1); | |
| 165 } | |
| 166 return timerData; | |
|
caryclark
2013/07/08 13:04:57
instead of returning the timerData, why not return
sglez
2013/07/08 22:00:34
Moved the body of get_data_result into this functi
| |
| 167 } | |
| 168 | |
| 169 static int tool_main(int argc, char** argv) { | |
| 170 SkAutoGraphics ag; | |
| 171 SkString usage; | |
| 172 usage.printf("Usage: filename [filename]*\n"); | |
| 173 | |
| 174 if (argc < 2) { | |
| 175 SkDebugf("%s\n", usage.c_str()); | |
| 176 } | |
| 177 | |
| 178 TimerData normalRecordData = | |
|
reed1
2013/07/08 12:07:03
Can this section be organized w/ tables of static
sglez
2013/07/08 22:00:34
Done. Thanks.
| |
| 179 benchmark_loop(argc, argv, benchmark_recording, kNormal_BenchmarkType); | |
| 180 TimerData rtreeRecordData = | |
| 181 benchmark_loop(argc, argv, benchmark_recording, kRTree_BenchmarkType); | |
| 182 TimerData normalPlaybackData = | |
| 183 benchmark_loop(argc, argv, benchmark_playback, kNormal_BenchmarkType); | |
| 184 TimerData rtreePlaybackData = | |
| 185 benchmark_loop(argc, argv, benchmark_playback, kRTree_BenchmarkType); | |
| 186 | |
| 187 SkScalar normalRecordResult = get_data_result(normalRecordData, "normal_reco rd"); | |
| 188 SkScalar rtreeRecordResult = get_data_result(rtreeRecordData, "rtree_record" ); | |
| 189 SkScalar normalPlaybackResult = get_data_result(normalPlaybackData, "normal_ playbak"); | |
| 190 SkScalar rtreePlaybackResult = get_data_result(rtreePlaybackData, "rtree_pla yback"); | |
| 191 SkASSERT(normalRecordResult != -1.0); | |
| 192 SkASSERT(rtreeRecordResult != -1.0); | |
| 193 SkASSERT(normalPlaybackResult != -1.0); | |
| 194 SkASSERT(rtreePlaybackResult != -1.0); | |
| 195 | |
| 196 SkASSERT(normalRecordResult != 0 && normalPlaybackResult != 0); | |
| 197 SkDebugf("Recording: Relative difference: %.4f\n", rtreeRecordResult / norma lRecordResult); | |
| 198 SkDebugf("Playback: Relative difference: %.4f\n", rtreePlaybackResult / nor malPlaybackResult); | |
| 199 | |
| 200 SkScalar times = | |
| 201 (kNumPlaybacks * (normalRecordResult - rtreeRecordResult)) / | |
| 202 (kNumRecordings * (rtreePlaybackResult - normalPlaybackResult)); | |
| 203 | |
| 204 SkDebugf("Number of playback repetitions for RTree to be worth it: %d (ratio : %.4f)\n", | |
| 205 SkScalarCeilToInt(times), times); | |
| 206 | |
| 207 return 0; | |
| 208 } | |
| 209 | |
| 210 int main(int argc, char** argv) { | |
| 211 return tool_main(argc, argv); | |
| 212 } | |
| 213 | |
| OLD | NEW |