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 #include "config.h" | |
32 | |
33 #include "RuntimeEnabledFeatures.h" | |
34 #include "core/platform/SharedBuffer.h" | |
35 #include "core/platform/image-decoders/ImageDecoder.h" | |
36 #include "public/web/WebKit.h" | |
37 #include "wtf/OwnArrayPtr.h" | |
38 #include "wtf/OwnPtr.h" | |
39 #include "wtf/PassOwnPtr.h" | |
40 | |
41 #if OS(WINDOWS) | |
42 #include <mmsystem.h> | |
43 #include <time.h> | |
44 #else | |
45 #include <sys/time.h> | |
46 #endif | |
47 | |
48 using namespace WebCore; | |
49 | |
50 #if OS(WINDOWS) | |
51 | |
52 // There's no real platform support herein, so adopt the win32 performance count er from WTF. | |
53 // http://trac.webkit.org/browser/trunk/Source/WTF/wtf/CurrentTime.cpp?rev=15243 8 | |
54 | |
55 static double lowResUTCTime() | |
56 { | |
57 FILETIME fileTime; | |
58 GetSystemTimeAsFileTime(&fileTime); | |
59 | |
60 // As per Windows documentation for FILETIME, copy the resulting FILETIME st ructure to a | |
61 // ULARGE_INTEGER structure using memcpy (using memcpy instead of direct ass ignment can | |
62 // prevent alignment faults on 64-bit Windows). | |
63 ULARGE_INTEGER dateTime; | |
64 memcpy(&dateTime, &fileTime, sizeof(dateTime)); | |
65 | |
66 // Number of 100 nanosecond between January 1, 1601 and January 1, 1970. | |
67 static const ULONGLONG epochBias = 116444736000000000ULL; | |
68 // Windows file times are in 100s of nanoseconds. | |
69 static const double hundredsOfNanosecondsPerMillisecond = 10000; | |
70 return (dateTime.QuadPart - epochBias) / hundredsOfNanosecondsPerMillisecond ; | |
71 } | |
72 | |
73 static LARGE_INTEGER qpcFrequency; | |
74 static bool syncedTime; | |
75 | |
76 static double highResUpTime() | |
77 { | |
78 // We use QPC, but only after sanity checking its result, due to bugs: | |
79 // http://support.microsoft.com/kb/274323 http://support.microsoft.com/kb/89 5980 | |
80 // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("you can get diffe rent results | |
81 // on different processors due to bugs in the basic input/output system (BIO S) or the | |
82 // hardware abstraction layer (HAL)."). | |
83 | |
84 static LARGE_INTEGER qpcLast; | |
85 static DWORD tickCountLast; | |
86 static bool inited; | |
87 | |
88 LARGE_INTEGER qpc; | |
89 QueryPerformanceCounter(&qpc); | |
90 DWORD tickCount = GetTickCount(); | |
91 | |
92 if (inited) { | |
93 __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFre quency.QuadPart; | |
94 __int64 tickCountElapsed; | |
95 if (tickCount >= tickCountLast) { | |
96 tickCountElapsed = (tickCount - tickCountLast); | |
97 } else { | |
98 __int64 tickCountLarge = tickCount + 0x100000000I64; | |
99 tickCountElapsed = tickCountLarge - tickCountLast; | |
100 } | |
101 | |
102 // Force a re-sync if QueryPerformanceCounter differs from GetTickCount( ) by more than | |
103 // 500ms. (The 500ms value is from http://support.microsoft.com/kb/27432 3). | |
104 __int64 diff = tickCountElapsed - qpcElapsed; | |
105 if (diff > 500 || diff < -500) | |
106 syncedTime = false; | |
107 } else { | |
108 inited = true; | |
109 } | |
110 | |
111 qpcLast = qpc; | |
112 tickCountLast = tickCount; | |
113 | |
114 return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart); | |
115 } | |
116 | |
117 static bool qpcAvailable() | |
118 { | |
119 static bool available; | |
120 static bool checked; | |
121 | |
122 if (checked) | |
123 return available; | |
124 | |
125 available = QueryPerformanceFrequency(&qpcFrequency); | |
126 checked = true; | |
127 return available; | |
128 } | |
129 | |
130 static double getCurrentTime() | |
131 { | |
132 // Use a combination of ftime and QueryPerformanceCounter. | |
133 // ftime returns the information we want, but doesn't have sufficient resolu tion. | |
134 // QueryPerformanceCounter has high resolution, but is only usable to measur e time intervals. | |
135 // To combine them, we call ftime and QueryPerformanceCounter initially. Lat er calls will | |
136 // use QueryPerformanceCounter by itself, adding the delta to the saved ftim e. | |
137 // We periodically re-sync to correct for drift. | |
138 static double syncLowResUTCTime; | |
139 static double syncHighResUpTime; | |
140 static double lastUTCTime; | |
141 | |
142 double lowResTime = lowResUTCTime(); | |
143 if (!qpcAvailable()) | |
144 return lowResTime / 1000.0; | |
145 | |
146 double highResTime = highResUpTime(); | |
147 if (!syncedTime) { | |
148 timeBeginPeriod(1); // increase time resolution around low-res time gett er | |
149 syncLowResUTCTime = lowResTime = lowResUTCTime(); | |
150 timeEndPeriod(1); // restore time resolution | |
151 syncHighResUpTime = highResTime; | |
152 syncedTime = true; | |
153 } | |
154 | |
155 double highResElapsed = highResTime - syncHighResUpTime; | |
156 double utc = syncLowResUTCTime + highResElapsed; | |
157 | |
158 // Force a clock re-sync if we've drifted. | |
159 double lowResElapsed = lowResTime - syncLowResUTCTime; | |
160 const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-r es accuracy | |
161 if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec) | |
162 syncedTime = false; | |
163 | |
164 // Make sure time doesn't run backwards (only correct if the difference is < 2 seconds, | |
165 // since DST or clock changes could occur). | |
166 const double backwardTimeLimit = 2000.0; | |
167 if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit) | |
168 return lastUTCTime / 1000.0; | |
169 lastUTCTime = utc; | |
170 return utc / 1000.0; | |
171 } | |
172 | |
173 #else | |
174 | |
175 static double getCurrentTime() | |
176 { | |
177 struct timeval now; | |
178 gettimeofday(&now, 0); | |
179 return now.tv_sec + now.tv_usec / 1000000.0; | |
180 } | |
181 | |
182 #endif | |
183 | |
184 static PassRefPtr<SharedBuffer> readFile(const char* fileName) | |
185 { | |
186 FILE* fp = fopen(fileName, "rb"); | |
187 if (!fp) { | |
188 fprintf(stderr, "Can't open %s\n", fileName); | |
189 exit(1); | |
190 } | |
191 | |
192 fseek(fp, 0, SEEK_END); | |
193 size_t fileSize = ftell(fp); | |
194 rewind(fp); | |
195 | |
196 OwnArrayPtr<unsigned char> buffer = adoptArrayPtr(new unsigned char[fileSize ]); | |
197 fread(buffer.get(), 1, fileSize, fp); | |
198 fclose(fp); | |
199 | |
200 return SharedBuffer::create(buffer.get(), fileSize); | |
201 } | |
202 | |
203 static bool decodeImageData(SharedBuffer* data) | |
204 { | |
205 OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, | |
206 ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileIgnore d); | |
207 decoder->setData(data, true); | |
208 | |
209 int frameCount = decoder->frameCount(); | |
210 for (int i = 0; i < frameCount; ++i) { | |
urvang (Google)
2013/07/29 22:38:36
If we always start decoding from the first frame,
| |
211 if (!decoder->frameBufferAtIndex(i)) | |
212 break; | |
213 } | |
214 | |
215 return !decoder->failed(); | |
216 } | |
217 | |
218 int main(int argc, char* argv[]) | |
abarth-chromium
2013/07/23 05:44:42
This file should probably be in Source/testing or
| |
219 { | |
220 if (argc < 2) { | |
221 fprintf(stderr, "Usage: %s file [iterations]\n", argv[0]); | |
222 exit(2); | |
223 } | |
224 | |
225 size_t iterations = 1000; | |
226 if (argc >= 3) { | |
227 char* end = 0; | |
228 iterations = strtol(argv[2], &end, 10); | |
229 if (*end != '\0' || !iterations) { | |
230 fprintf(stderr, "Second argument should be number of iterations. " | |
231 "The default is 1000. You supplied %s\n", argv[2]); | |
232 exit(2); | |
233 } | |
234 } | |
235 | |
236 class DummyWebKitPlatformSupport : public WebKit::Platform { | |
237 public: | |
238 const unsigned char* getTraceCategoryEnabledFlag(const char*) | |
239 { return (const unsigned char *) "nope-none-nada"; } | |
240 void cryptographicallyRandomValues(unsigned char*, size_t) { } | |
241 }; | |
242 | |
243 WebKit::initializeWithoutV8(new DummyWebKitPlatformSupport()); | |
244 WebCore::RuntimeEnabledFeatures::setAnimatedWebPEnabled(true); | |
245 | |
246 RefPtr<SharedBuffer> data = readFile(argv[1]); | |
247 double totalTime = 0.0; | |
248 | |
249 for (size_t i = 0; i < iterations; ++i) { | |
250 double startTime = getCurrentTime(); | |
251 bool decoded = decodeImageData(data.get()); | |
252 double elapsedTime = getCurrentTime() - startTime; | |
253 totalTime += elapsedTime; | |
254 if (!decoded) { | |
255 fprintf(stderr, "Image decode failed.\n"); | |
256 exit(3); | |
257 } | |
258 } | |
259 | |
260 double averageTime = totalTime / static_cast<double>(iterations); | |
261 printf("%f %f\n", totalTime, averageTime); | |
262 return 0; | |
263 } | |
OLD | NEW |