Index: Source/WebKit/chromium/src/ImageDecodeBench.cpp |
diff --git a/Source/WebKit/chromium/src/ImageDecodeBench.cpp b/Source/WebKit/chromium/src/ImageDecodeBench.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ba9c8a0437bfcf622a0a2dce0cb3b89ff6f569c3 |
--- /dev/null |
+++ b/Source/WebKit/chromium/src/ImageDecodeBench.cpp |
@@ -0,0 +1,266 @@ |
+/* |
+ * Copyright (C) 2013 Google Inc. All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions are |
+ * met: |
+ * |
+ * * Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * * Redistributions in binary form must reproduce the above |
+ * copyright notice, this list of conditions and the following disclaimer |
+ * in the documentation and/or other materials provided with the |
+ * distribution. |
+ * * Neither the name of Google Inc. nor the names of its |
+ * contributors may be used to endorse or promote products derived from |
+ * this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ */ |
+ |
+// % 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_
|
+ |
+#include "config.h" |
+ |
+#include "RuntimeEnabledFeatures.h" |
+#include "core/platform/SharedBuffer.h" |
+#include "core/platform/image-decoders/ImageDecoder.h" |
+#include "public/web/WebKit.h" |
+#include "wtf/OwnPtr.h" |
+#include "wtf/PassOwnPtr.h" |
+ |
+#if OS(WINDOWS) |
+#include <mmsystem.h> |
+#include <time.h> |
+#else |
+#include <sys/time.h> |
+#endif |
+ |
+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.
|
+using namespace WebCore; |
+ |
+#if OS(WINDOWS) |
+ |
+// Adopt the performance counter from WTF:currentTime() since chromium's currentTime() is |
+// not the high performance counter anymore, making it unsuitable for decode benchmarking. |
+// http://trac.webkit.org/browser/trunk/Source/WTF/wtf/CurrentTime.cpp?rev=152438 |
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
|
+ |
+static double lowResUTCTime() |
+{ |
+ FILETIME fileTime; |
+ GetSystemTimeAsFileTime(&fileTime); |
+ |
+ // As per Windows documentation for FILETIME, copy the resulting FILETIME structure to a |
+ // ULARGE_INTEGER structure using memcpy (using memcpy instead of direct assignment can |
+ // prevent alignment faults on 64-bit Windows). |
+ ULARGE_INTEGER dateTime; |
+ memcpy(&dateTime, &fileTime, sizeof(dateTime)); |
+ |
+ // Number of 100 nanosecond between January 1, 1601 and January 1, 1970. |
+ static const ULONGLONG epochBias = 116444736000000000ULL; |
+ // Windows file times are in 100s of nanoseconds. |
+ static const double hundredsOfNanosecondsPerMillisecond = 10000; |
+ return (dateTime.QuadPart - epochBias) / hundredsOfNanosecondsPerMillisecond; |
+} |
+ |
+static LARGE_INTEGER qpcFrequency; |
+static bool syncedTime; |
+ |
+static double highResUpTime() |
+{ |
+ // We use QPC, but only after sanity checking its result, due to bugs: |
+ // http://support.microsoft.com/kb/274323 http://support.microsoft.com/kb/895980 |
+ // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("you can get different results |
+ // on different processors due to bugs in the basic input/output system (BIOS) or the |
+ // hardware abstraction layer (HAL)."). |
+ |
+ static LARGE_INTEGER qpcLast; |
+ static DWORD tickCountLast; |
+ static bool inited; |
+ |
+ LARGE_INTEGER qpc; |
+ QueryPerformanceCounter(&qpc); |
+ DWORD tickCount = GetTickCount(); |
+ |
+ if (inited) { |
+ __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart; |
+ __int64 tickCountElapsed; |
+ if (tickCount >= tickCountLast) { |
+ tickCountElapsed = (tickCount - tickCountLast); |
+ } else { |
+ __int64 tickCountLarge = tickCount + 0x100000000I64; |
+ tickCountElapsed = tickCountLarge - tickCountLast; |
+ } |
+ |
+ // Force a re-sync if QueryPerformanceCounter differs from GetTickCount() by more than |
+ // 500ms. (The 500ms value is from http://support.microsoft.com/kb/274323). |
+ __int64 diff = tickCountElapsed - qpcElapsed; |
+ if (diff > 500 || diff < -500) |
+ syncedTime = false; |
+ } else { |
+ inited = true; |
+ } |
+ |
+ qpcLast = qpc; |
+ tickCountLast = tickCount; |
+ |
+ return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart); |
+} |
+ |
+static bool qpcAvailable() |
+{ |
+ static bool available; |
+ static bool checked; |
+ |
+ if (checked) |
+ return available; |
+ |
+ available = QueryPerformanceFrequency(&qpcFrequency); |
+ checked = true; |
+ return available; |
+} |
+ |
+static double getCurrentTime() |
+{ |
+ // Use a combination of ftime and QueryPerformanceCounter. |
+ // ftime returns the information we want, but doesn't have sufficient resolution. |
+ // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals. |
+ // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will |
+ // use QueryPerformanceCounter by itself, adding the delta to the saved ftime. |
+ // We periodically re-sync to correct for drift. |
+ static double syncLowResUTCTime; |
+ static double syncHighResUpTime; |
+ static double lastUTCTime; |
+ |
+ double lowResTime = lowResUTCTime(); |
+ if (!qpcAvailable()) |
+ return lowResTime / 1000.0; |
+ |
+ double highResTime = highResUpTime(); |
+ if (!syncedTime) { |
+ timeBeginPeriod(1); // increase time resolution around low-res time getter |
+ syncLowResUTCTime = lowResTime = lowResUTCTime(); |
+ timeEndPeriod(1); // restore time resolution |
+ syncHighResUpTime = highResTime; |
+ syncedTime = true; |
+ } |
+ |
+ double highResElapsed = highResTime - syncHighResUpTime; |
+ double utc = syncLowResUTCTime + highResElapsed; |
+ |
+ // Force a clock re-sync if we've drifted. |
+ double lowResElapsed = lowResTime - syncLowResUTCTime; |
+ const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy |
+ if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec) |
+ syncedTime = false; |
+ |
+ // Make sure time doesn't run backwards (only correct if the difference is < 2 seconds, |
+ // since DST or clock changes could occur). |
+ const double backwardTimeLimit = 2000.0; |
+ if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit) |
+ return lastUTCTime / 1000.0; |
+ lastUTCTime = utc; |
+ return utc / 1000.0; |
+} |
+ |
+#else |
+ |
+static double getCurrentTime() |
+{ |
+ struct timeval now; |
+ gettimeofday(&now, 0); |
+ return now.tv_sec + now.tv_usec / 1000000.0; |
+} |
+ |
+#endif |
+ |
+static PassRefPtr<SharedBuffer> readFile(const char* fileName) |
+{ |
+ FILE* fp = fopen(fileName, "rb"); |
+ if (!fp) { |
+ fprintf(stderr, "Can't open %s\n", fileName); |
+ exit(1); |
+ } |
+ |
+ fseek(fp, 0, SEEK_END); |
+ size_t fileSize = ftell(fp); |
+ rewind(fp); |
+ |
+ 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.
|
+ fread(buffer, 1, fileSize, fp); |
+ fclose(fp); |
+ |
+ return SharedBuffer::create(buffer, fileSize); |
+} |
+ |
+static bool decodeImageData(SharedBuffer* data) |
+{ |
+ OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, |
+ ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileIgnored); |
+ decoder->setData(data, true); |
+ |
+ int frameCount = decoder->frameCount(); |
+ for (int i = 0; i < frameCount; ++i) { |
+ if (!decoder->frameBufferAtIndex(i)) |
+ break; |
+ } |
+ |
+ return !decoder->failed(); |
+} |
+ |
+int main(int argc, char* argv[]) |
+{ |
+ if (argc < 2) { |
+ fprintf(stderr, "Usage: %s file [iterations]\n", argv[0]); |
+ exit(2); |
+ } |
+ |
+ size_t iterations = 1000; |
+ if (argc >= 3) { |
+ char* end = 0; |
+ iterations = strtol(argv[2], &end, 10); |
+ if (*end != '\0' || !iterations) { |
+ fprintf(stderr, "Second argument should be number of iterations. " |
+ "The default is 1000. You supplied %s\n", argv[2]); |
+ exit(2); |
+ } |
+ } |
+ |
+ 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
|
+ public: |
+ const unsigned char* getTraceCategoryEnabledFlag(const char*) |
+ { return (const unsigned char *) "none-nada-нет"; } |
+ void cryptographicallyRandomValues(unsigned char*, size_t) { } |
+ }; |
+ |
+ WebKit::initializeWithoutV8(new DummyWebKitPlatformSupport()); |
+ WebCore::RuntimeEnabledFeatures::setAnimatedWebPEnabled(true); |
+ |
+ RefPtr<SharedBuffer> data = readFile(argv[1]); |
+ double totalTime = 0.0; |
+ |
+ for (size_t i = 0; i < iterations; ++i) { |
+ double startTime = getCurrentTime(); |
+ bool decoded = decodeImageData(data.get()); |
+ double elapsedTime = getCurrentTime() - startTime; |
+ totalTime += elapsedTime; |
+ if (!decoded) { |
+ fprintf(stderr, "Image decode failed.\n"); |
+ exit(3); |
+ } |
+ } |
+ |
+ double averageTime = totalTime / static_cast<double>(iterations); |
+ printf("%f %f\n", totalTime, averageTime); |
+ return 0; |
+} |