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 "Timer.h" | |
9 #include "Benchmark.h" | |
10 #include "LazyDecodeBitmap.h" | |
11 #include "PictureBenchmark.h" | |
12 #include "PictureRenderer.h" | |
13 #include "SkCommandLineFlags.h" | |
14 #include "SkForceLinking.h" | |
15 #include "SkGraphics.h" | |
16 #include "SkStream.h" | |
17 #include "SkString.h" | |
18 #include "SkTArray.h" | |
19 | |
20 typedef sk_tools::PictureRenderer::BBoxHierarchyType BBoxType; | |
21 static const int kBBoxTypeCount = sk_tools::PictureRenderer::kLast_BBoxHierarchy
Type + 1; | |
22 | |
23 | |
24 DEFINE_string2(skps, r, "", "The list of SKPs to benchmark."); | |
25 DEFINE_string(bb_types, "", "The set of bbox types to test. If empty, all are te
sted. " | |
26 "Should be one or more of none, rtree, tilegrid."); | |
27 DEFINE_int32(record, 100, "Number of times to record each SKP."); | |
28 DEFINE_int32(playback, 1, "Number of times to playback each SKP."); | |
29 DEFINE_int32(tilesize, 256, "The size of a tile."); | |
30 | |
31 struct Measurement { | |
32 SkString fName; | |
33 double fRecordAverage[kBBoxTypeCount]; | |
34 double fPlaybackAverage[kBBoxTypeCount]; | |
35 }; | |
36 | |
37 const char* kBBoxHierarchyTypeNames[kBBoxTypeCount] = { | |
38 "none", // kNone_BBoxHierarchyType | |
39 "rtree", // kRTree_BBoxHierarchyType | |
40 }; | |
41 | |
42 static SkPicture* pic_from_path(const char path[]) { | |
43 SkFILEStream stream(path); | |
44 if (!stream.isValid()) { | |
45 SkDebugf("-- Can't open '%s'\n", path); | |
46 return NULL; | |
47 } | |
48 return SkPicture::CreateFromStream(&stream, &sk_tools::LazyDecodeBitmap); | |
49 } | |
50 | |
51 /** | |
52 * This function is the sink to which all work ends up going. | |
53 * @param renderer The renderer to use to perform the work. | |
54 * To measure rendering, use a TiledPictureRenderer. | |
55 * To measure recording, use a RecordPictureRenderer. | |
56 * @param bBoxType The bounding box hierarchy type to use. | |
57 * @param pic The picture to draw to the renderer. | |
58 * @param numRepeats The number of times to repeat the draw. | |
59 * @param timer The timer used to benchmark the work. | |
60 */ | |
61 static void do_benchmark_work(sk_tools::PictureRenderer* renderer, | |
62 BBoxType bBoxType, | |
63 SkPicture* pic, | |
64 const int numRepeats, | |
65 Timer* timer) { | |
66 renderer->setBBoxHierarchyType(bBoxType); | |
67 renderer->init(pic, NULL, NULL, NULL, false, false); | |
68 | |
69 SkDebugf("%s %d times...\n", renderer->getConfigName().c_str(), numRepeats); | |
70 for (int i = 0; i < numRepeats; ++i) { | |
71 renderer->setup(); | |
72 // Render once to fill caches | |
73 renderer->render(); | |
74 // Render again to measure | |
75 timer->start(); | |
76 renderer->render(); | |
77 timer->end(); | |
78 } | |
79 } | |
80 | |
81 int tool_main(int argc, char** argv); | |
82 int tool_main(int argc, char** argv) { | |
83 SkCommandLineFlags::Parse(argc, argv); | |
84 SkAutoGraphics ag; | |
85 bool includeBBoxType[kBBoxTypeCount]; | |
86 for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { | |
87 includeBBoxType[bBoxType] = (FLAGS_bb_types.count() == 0) || | |
88 FLAGS_bb_types.contains(kBBoxHierarchyTypeNames[bBoxType]); | |
89 } | |
90 // go through all the pictures | |
91 SkTArray<Measurement> measurements; | |
92 for (int index = 0; index < FLAGS_skps.count(); ++index) { | |
93 const char* path = FLAGS_skps[index]; | |
94 SkPicture* picture = pic_from_path(path); | |
95 if (NULL == picture) { | |
96 SkDebugf("Couldn't create picture. Ignoring path: %s\n", path); | |
97 continue; | |
98 } | |
99 SkDebugf("Benchmarking path: %s\n", path); | |
100 Measurement& measurement = measurements.push_back(); | |
101 measurement.fName = path; | |
102 for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { | |
103 if (!includeBBoxType[bBoxType]) { continue; } | |
104 if (FLAGS_playback > 0) { | |
105 #if SK_SUPPORT_GPU | |
106 GrContext::Options grContextOpts; | |
107 sk_tools::TiledPictureRenderer playbackRenderer(grContextOpts); | |
108 #else | |
109 sk_tools::TiledPictureRenderer playbackRenderer; | |
110 #endif | |
111 Timer playbackTimer; | |
112 do_benchmark_work(&playbackRenderer, (BBoxType)bBoxType, | |
113 picture, FLAGS_playback, &playbackTimer); | |
114 measurement.fPlaybackAverage[bBoxType] = playbackTimer.fCpu; | |
115 } | |
116 if (FLAGS_record > 0) { | |
117 #if SK_SUPPORT_GPU | |
118 GrContext::Options grContextOpts; | |
119 sk_tools::RecordPictureRenderer recordRenderer(grContextOpts); | |
120 #else | |
121 sk_tools::RecordPictureRenderer recordRenderer; | |
122 #endif | |
123 Timer recordTimer; | |
124 do_benchmark_work(&recordRenderer, (BBoxType)bBoxType, | |
125 picture, FLAGS_record, &recordTimer); | |
126 measurement.fRecordAverage[bBoxType] = recordTimer.fCpu; | |
127 } | |
128 } | |
129 } | |
130 | |
131 Measurement globalMeasurement; | |
132 for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { | |
133 if (!includeBBoxType[bBoxType]) { continue; } | |
134 globalMeasurement.fPlaybackAverage[bBoxType] = 0; | |
135 globalMeasurement.fRecordAverage[bBoxType] = 0; | |
136 for (int index = 0; index < measurements.count(); ++index) { | |
137 const Measurement& measurement = measurements[index]; | |
138 globalMeasurement.fPlaybackAverage[bBoxType] += | |
139 measurement.fPlaybackAverage[bBoxType]; | |
140 globalMeasurement.fRecordAverage[bBoxType] += | |
141 measurement.fRecordAverage[bBoxType]; | |
142 } | |
143 globalMeasurement.fPlaybackAverage[bBoxType] /= measurements.count(); | |
144 globalMeasurement.fRecordAverage[bBoxType] /= measurements.count(); | |
145 } | |
146 | |
147 // Output gnuplot readable histogram data.. | |
148 const char* pbTitle = "bbh_shootout_playback.dat"; | |
149 const char* recTitle = "bbh_shootout_record.dat"; | |
150 SkFILEWStream playbackOut(pbTitle); | |
151 SkFILEWStream recordOut(recTitle); | |
152 recordOut.writeText("# "); | |
153 playbackOut.writeText("# "); | |
154 SkDebugf("---\n"); | |
155 for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { | |
156 if (!includeBBoxType[bBoxType]) { continue; } | |
157 SkString out; | |
158 out.printf("%s ", kBBoxHierarchyTypeNames[bBoxType]); | |
159 recordOut.writeText(out.c_str()); | |
160 playbackOut.writeText(out.c_str()); | |
161 | |
162 if (FLAGS_record > 0) { | |
163 SkDebugf("Average %s recording time: %.3fms\n", | |
164 kBBoxHierarchyTypeNames[bBoxType], | |
165 globalMeasurement.fRecordAverage[bBoxType]); | |
166 } | |
167 if (FLAGS_playback > 0) { | |
168 SkDebugf("Average %s playback time: %.3fms\n", | |
169 kBBoxHierarchyTypeNames[bBoxType], | |
170 globalMeasurement.fPlaybackAverage[bBoxType]); | |
171 } | |
172 } | |
173 recordOut.writeText("\n"); | |
174 playbackOut.writeText("\n"); | |
175 // Write to file, and save recording averages. | |
176 for (int index = 0; index < measurements.count(); ++index) { | |
177 const Measurement& measurement = measurements[index]; | |
178 SkString pbLine; | |
179 SkString recLine; | |
180 | |
181 pbLine.printf("%d", index); | |
182 recLine.printf("%d", index); | |
183 for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { | |
184 if (!includeBBoxType[bBoxType]) { continue; } | |
185 pbLine.appendf(" %f", measurement.fPlaybackAverage[bBoxType]); | |
186 recLine.appendf(" %f", measurement.fRecordAverage[bBoxType]); | |
187 } | |
188 pbLine.appendf("\n"); | |
189 recLine.appendf("\n"); | |
190 playbackOut.writeText(pbLine.c_str()); | |
191 recordOut.writeText(recLine.c_str()); | |
192 } | |
193 SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitl
e); | |
194 return 0; | |
195 } | |
196 | |
197 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | |
198 int main(int argc, char** argv) { | |
199 return tool_main(argc, argv); | |
200 } | |
201 #endif | |
OLD | NEW |