1 /* 2 * Copyright 2012 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 #include "bench/Benchmark.h" 8 #include "include/core/SkCanvas.h" 9 #include "include/core/SkString.h" 10 #include "include/private/base/SkTemplates.h" 11 #include "src/base/SkRandom.h" 12 #include "src/core/SkChecksum.h" 13 #include "src/core/SkMD5.h" 14 15 #include <memory> 16 17 enum ChecksumType { 18 kMD5_ChecksumType, 19 kWyhash_ChecksumType, 20 }; 21 22 class ComputeChecksumBench : public Benchmark { 23 public: 24 // All instances of this benchmark compute a checksum over 64K (or slightly less, if the 25 // block size doesn't divide evenly). 26 constexpr static size_t kBufferSize = 64 * 1024; 27 28 ChecksumType fType; 29 size_t fBlockSize; 30 SkString fName; 31 std::unique_ptr<uint8_t[]> fData; 32 ComputeChecksumBench(ChecksumType type,size_t blockSize)33 ComputeChecksumBench(ChecksumType type, size_t blockSize) : fType(type), fBlockSize(blockSize) { 34 SkASSERT(blockSize <= kBufferSize); 35 36 switch (fType) { 37 case kMD5_ChecksumType: fName = "compute_md5"; break; 38 case kWyhash_ChecksumType: fName = "compute_wyhash"; break; 39 } 40 fName.appendf("_%d", static_cast<int>(fBlockSize)); 41 } 42 isSuitableFor(Backend backend)43 bool isSuitableFor(Backend backend) override { return backend == Backend::kNonRendering; } onGetName()44 const char* onGetName() override { return fName.c_str(); } 45 onPreDraw(SkCanvas *)46 void onPreDraw(SkCanvas*) override { 47 fData.reset(new uint8_t[kBufferSize]); 48 49 SkRandom rand; 50 for (size_t i = 0; i < kBufferSize; ++i) { 51 fData[i] = rand.nextBits(8); 52 } 53 } 54 onPostDraw(SkCanvas *)55 void onPostDraw(SkCanvas*) override { 56 fData.reset(); 57 } 58 onDraw(int loops,SkCanvas *)59 void onDraw(int loops, SkCanvas*) override { 60 volatile uint32_t result = 0; 61 const size_t blockCount = kBufferSize / fBlockSize; 62 const uint8_t* bufEnd = fData.get() + (blockCount * fBlockSize); 63 for (int i = 0; i < loops; i++) { 64 for (const uint8_t* buf = fData.get(); buf < bufEnd; buf += fBlockSize) { 65 switch (fType) { 66 case kMD5_ChecksumType: { 67 SkMD5 md5; 68 md5.write(buf, fBlockSize); 69 (void)md5.finish(); 70 break; 71 } 72 case kWyhash_ChecksumType: 73 result = SkChecksum::Hash32(buf, fBlockSize); 74 break; 75 } 76 } 77 } 78 sk_ignore_unused_variable(result); 79 } 80 }; 81 82 /////////////////////////////////////////////////////////////////////////////// 83 84 DEF_BENCH( return new ComputeChecksumBench(kMD5_ChecksumType, 1024); ) 85 86 #define DEF_CHECKSUM_BENCH(T) \ 87 DEF_BENCH( return new ComputeChecksumBench(T, 4); ) \ 88 DEF_BENCH( return new ComputeChecksumBench(T, 8); ) \ 89 DEF_BENCH( return new ComputeChecksumBench(T, 15); ) \ 90 DEF_BENCH( return new ComputeChecksumBench(T, 16); ) \ 91 DEF_BENCH( return new ComputeChecksumBench(T, 31); ) \ 92 DEF_BENCH( return new ComputeChecksumBench(T, 32); ) \ 93 DEF_BENCH( return new ComputeChecksumBench(T, 96); ) \ 94 DEF_BENCH( return new ComputeChecksumBench(T, 1024); ) 95 96 DEF_CHECKSUM_BENCH(kWyhash_ChecksumType) 97