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 |