OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 // % ninja -C out/Release image_decode_bench | |
Alpha Left Google
2013/07/10 18:51:07
There's no need to add comments about building it.
Noel Gordon
2013/07/11 03:09:00
removed - there is no build item for image_decode_
| |
32 | |
33 #include "config.h" | |
34 | |
35 #include "RuntimeEnabledFeatures.h" | |
36 #include "core/platform/SharedBuffer.h" | |
37 #include "core/platform/image-decoders/ImageDecoder.h" | |
38 #include "public/web/WebKit.h" | |
39 #include "wtf/OwnPtr.h" | |
40 #include "wtf/PassOwnPtr.h" | |
41 | |
42 #if OS(WINDOWS) | |
43 #include <mmsystem.h> | |
44 #include <time.h> | |
45 #else | |
46 #include <sys/time.h> | |
47 #endif | |
48 | |
49 using namespace std; | |
Alpha Left Google
2013/07/10 18:51:07
You're not using <iostream> you can get rid of thi
Noel Gordon
2013/07/11 03:09:00
Done.
| |
50 using namespace WebCore; | |
51 | |
52 #if OS(WINDOWS) | |
53 | |
54 // Adopt the performance counter from WTF:currentTime() since chromium's current Time() is | |
55 // not the high performance counter anymore, making it unsuitable for decode ben chmarking. | |
56 // http://trac.webkit.org/browser/trunk/Source/WTF/wtf/CurrentTime.cpp?rev=15243 8 | |
jamesr
2013/07/10 19:20:33
nack, just use WTF::monotonicallyIncreasingTime().
Noel Gordon
2013/07/11 03:09:00
Ah if only we had it. There's no real platform su
| |
57 | |
58 static double lowResUTCTime() | |
59 { | |
60 FILETIME fileTime; | |
61 GetSystemTimeAsFileTime(&fileTime); | |
62 | |
63 // As per Windows documentation for FILETIME, copy the resulting FILETIME st ructure to a | |
64 // ULARGE_INTEGER structure using memcpy (using memcpy instead of direct ass ignment can | |
65 // prevent alignment faults on 64-bit Windows). | |
66 ULARGE_INTEGER dateTime; | |
67 memcpy(&dateTime, &fileTime, sizeof(dateTime)); | |
68 | |
69 // Number of 100 nanosecond between January 1, 1601 and January 1, 1970. | |
70 static const ULONGLONG epochBias = 116444736000000000ULL; | |
71 // Windows file times are in 100s of nanoseconds. | |
72 static const double hundredsOfNanosecondsPerMillisecond = 10000; | |
73 return (dateTime.QuadPart - epochBias) / hundredsOfNanosecondsPerMillisecond ; | |
74 } | |
75 | |
76 static LARGE_INTEGER qpcFrequency; | |
77 static bool syncedTime; | |
78 | |
79 static double highResUpTime() | |
80 { | |
81 // We use QPC, but only after sanity checking its result, due to bugs: | |
82 // http://support.microsoft.com/kb/274323 http://support.microsoft.com/kb/89 5980 | |
83 // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("you can get diffe rent results | |
84 // on different processors due to bugs in the basic input/output system (BIO S) or the | |
85 // hardware abstraction layer (HAL)."). | |
86 | |
87 static LARGE_INTEGER qpcLast; | |
88 static DWORD tickCountLast; | |
89 static bool inited; | |
90 | |
91 LARGE_INTEGER qpc; | |
92 QueryPerformanceCounter(&qpc); | |
93 DWORD tickCount = GetTickCount(); | |
94 | |
95 if (inited) { | |
96 __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFre quency.QuadPart; | |
97 __int64 tickCountElapsed; | |
98 if (tickCount >= tickCountLast) { | |
99 tickCountElapsed = (tickCount - tickCountLast); | |
100 } else { | |
101 __int64 tickCountLarge = tickCount + 0x100000000I64; | |
102 tickCountElapsed = tickCountLarge - tickCountLast; | |
103 } | |
104 | |
105 // Force a re-sync if QueryPerformanceCounter differs from GetTickCount( ) by more than | |
106 // 500ms. (The 500ms value is from http://support.microsoft.com/kb/27432 3). | |
107 __int64 diff = tickCountElapsed - qpcElapsed; | |
108 if (diff > 500 || diff < -500) | |
109 syncedTime = false; | |
110 } else { | |
111 inited = true; | |
112 } | |
113 | |
114 qpcLast = qpc; | |
115 tickCountLast = tickCount; | |
116 | |
117 return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart); | |
118 } | |
119 | |
120 static bool qpcAvailable() | |
121 { | |
122 static bool available; | |
123 static bool checked; | |
124 | |
125 if (checked) | |
126 return available; | |
127 | |
128 available = QueryPerformanceFrequency(&qpcFrequency); | |
129 checked = true; | |
130 return available; | |
131 } | |
132 | |
133 static double getCurrentTime() | |
134 { | |
135 // Use a combination of ftime and QueryPerformanceCounter. | |
136 // ftime returns the information we want, but doesn't have sufficient resolu tion. | |
137 // QueryPerformanceCounter has high resolution, but is only usable to measur e time intervals. | |
138 // To combine them, we call ftime and QueryPerformanceCounter initially. Lat er calls will | |
139 // use QueryPerformanceCounter by itself, adding the delta to the saved ftim e. | |
140 // We periodically re-sync to correct for drift. | |
141 static double syncLowResUTCTime; | |
142 static double syncHighResUpTime; | |
143 static double lastUTCTime; | |
144 | |
145 double lowResTime = lowResUTCTime(); | |
146 if (!qpcAvailable()) | |
147 return lowResTime / 1000.0; | |
148 | |
149 double highResTime = highResUpTime(); | |
150 if (!syncedTime) { | |
151 timeBeginPeriod(1); // increase time resolution around low-res time gett er | |
152 syncLowResUTCTime = lowResTime = lowResUTCTime(); | |
153 timeEndPeriod(1); // restore time resolution | |
154 syncHighResUpTime = highResTime; | |
155 syncedTime = true; | |
156 } | |
157 | |
158 double highResElapsed = highResTime - syncHighResUpTime; | |
159 double utc = syncLowResUTCTime + highResElapsed; | |
160 | |
161 // Force a clock re-sync if we've drifted. | |
162 double lowResElapsed = lowResTime - syncLowResUTCTime; | |
163 const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-r es accuracy | |
164 if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec) | |
165 syncedTime = false; | |
166 | |
167 // Make sure time doesn't run backwards (only correct if the difference is < 2 seconds, | |
168 // since DST or clock changes could occur). | |
169 const double backwardTimeLimit = 2000.0; | |
170 if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit) | |
171 return lastUTCTime / 1000.0; | |
172 lastUTCTime = utc; | |
173 return utc / 1000.0; | |
174 } | |
175 | |
176 #else | |
177 | |
178 static double getCurrentTime() | |
179 { | |
180 struct timeval now; | |
181 gettimeofday(&now, 0); | |
182 return now.tv_sec + now.tv_usec / 1000000.0; | |
183 } | |
184 | |
185 #endif | |
186 | |
187 static PassRefPtr<SharedBuffer> readFile(const char* fileName) | |
188 { | |
189 FILE* fp = fopen(fileName, "rb"); | |
190 if (!fp) { | |
191 fprintf(stderr, "Can't open %s\n", fileName); | |
192 exit(1); | |
193 } | |
194 | |
195 fseek(fp, 0, SEEK_END); | |
196 size_t fileSize = ftell(fp); | |
197 rewind(fp); | |
198 | |
199 unsigned char* buffer = new unsigned char[fileSize]; | |
Alpha Left Google
2013/07/10 18:51:07
delete [] buffer after use.
Noel Gordon
2013/07/11 03:09:00
used OwnArrayPtr.
| |
200 fread(buffer, 1, fileSize, fp); | |
201 fclose(fp); | |
202 | |
203 return SharedBuffer::create(buffer, fileSize); | |
204 } | |
205 | |
206 static bool decodeImageData(SharedBuffer* data) | |
207 { | |
208 OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, | |
209 ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileIgnore d); | |
210 decoder->setData(data, true); | |
211 | |
212 int frameCount = decoder->frameCount(); | |
213 for (int i = 0; i < frameCount; ++i) { | |
214 if (!decoder->frameBufferAtIndex(i)) | |
215 break; | |
216 } | |
217 | |
218 return !decoder->failed(); | |
219 } | |
220 | |
221 int main(int argc, char* argv[]) | |
222 { | |
223 if (argc < 2) { | |
224 fprintf(stderr, "Usage: %s file [iterations]\n", argv[0]); | |
225 exit(2); | |
226 } | |
227 | |
228 size_t iterations = 1000; | |
229 if (argc >= 3) { | |
230 char* end = 0; | |
231 iterations = strtol(argv[2], &end, 10); | |
232 if (*end != '\0' || !iterations) { | |
233 fprintf(stderr, "Second argument should be number of iterations. " | |
234 "The default is 1000. You supplied %s\n", argv[2]); | |
235 exit(2); | |
236 } | |
237 } | |
238 | |
239 class DummyWebKitPlatformSupport : public WebKit::Platform { | |
Alpha Left Google
2013/07/10 18:51:07
Class definition like this looks kind of weird. I
Noel Gordon
2013/07/11 03:09:00
Me either, and the style presubmit is mute about i
| |
240 public: | |
241 const unsigned char* getTraceCategoryEnabledFlag(const char*) | |
242 { return (const unsigned char *) "none-nada-нет"; } | |
243 void cryptographicallyRandomValues(unsigned char*, size_t) { } | |
244 }; | |
245 | |
246 WebKit::initializeWithoutV8(new DummyWebKitPlatformSupport()); | |
247 WebCore::RuntimeEnabledFeatures::setAnimatedWebPEnabled(true); | |
248 | |
249 RefPtr<SharedBuffer> data = readFile(argv[1]); | |
250 double totalTime = 0.0; | |
251 | |
252 for (size_t i = 0; i < iterations; ++i) { | |
253 double startTime = getCurrentTime(); | |
254 bool decoded = decodeImageData(data.get()); | |
255 double elapsedTime = getCurrentTime() - startTime; | |
256 totalTime += elapsedTime; | |
257 if (!decoded) { | |
258 fprintf(stderr, "Image decode failed.\n"); | |
259 exit(3); | |
260 } | |
261 } | |
262 | |
263 double averageTime = totalTime / static_cast<double>(iterations); | |
264 printf("%f %f\n", totalTime, averageTime); | |
265 return 0; | |
266 } | |
OLD | NEW |