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 |