18af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com/* 28af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com * Copyright 2013 Google Inc. 38af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com * 48af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com * Use of this source code is governed by a BSD-style license that can be 58af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com * found in the LICENSE file. 68af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com */ 78af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 8f168b86d7fafc5c20c87bebc6fd393cb17e120catfarina#include "Benchmark.h" 98af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com#include "SkCanvas.h" 1067a3271f0de9ccc32d559b042b862528272047ccmtklein#include "SkChecksum.h" 118af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com#include "SkPaint.h" 128af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com#include "SkString.h" 138af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com#include "SkTemplates.h" 148af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 15664621a19e7ca5236ae4fce19e3ffd97f047b64dreed@google.com#include "gUniqueGlyphIDs.h" 16c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com#define gUniqueGlyphIDs_Sentinel 0xFFFF 178af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 18c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic int count_glyphs(const uint16_t start[]) { 19c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com const uint16_t* curr = start; 20c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com while (*curr != gUniqueGlyphIDs_Sentinel) { 21c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com curr += 1; 228af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 238b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com return static_cast<int>(curr - start); 24c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 258af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 26f168b86d7fafc5c20c87bebc6fd393cb17e120catfarinaclass FontCacheBench : public Benchmark { 27c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.compublic: 28410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com FontCacheBench() {} 29a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 308af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.comprotected: 3136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* onGetName() override { 328af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com return "fontcache"; 338af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 34a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 352880df2609eba09b555ca37be04b6ad89290c765Tom Hudson void onDraw(int loops, SkCanvas* canvas) override { 368af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com SkPaint paint; 378af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com this->setupPaint(&paint); 388af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 39a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 402fef6d2bda33b348133843e22c1009504c6fc209reed@google.com const uint16_t* array = gUniqueGlyphIDs; 41c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com while (*array != gUniqueGlyphIDs_Sentinel) { 428b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com int count = count_glyphs(array); 433361471a3504ecd0351ff70f4c42d8d6fee963d4commit-bot@chromium.org for (int i = 0; i < loops; ++i) { 44c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com paint.measureText(array, count * sizeof(uint16_t)); 458af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 46c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com array += count + 1; // skip the sentinel 478af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 488af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 49a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 50c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comprivate: 51f168b86d7fafc5c20c87bebc6fd393cb17e120catfarina typedef Benchmark INHERITED; 52c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com}; 53c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 54c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com/////////////////////////////////////////////////////////////////////////////// 55c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 56c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic uint32_t rotr(uint32_t value, unsigned bits) { 57c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return (value >> bits) | (value << (32 - bits)); 58c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 59c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 60c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comtypedef uint32_t (*HasherProc)(uint32_t); 61c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 62c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic uint32_t hasher0(uint32_t value) { 63c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com value = value ^ (value >> 16); 64c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return value ^ (value >> 8); 65c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 66c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 67c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic const struct { 68c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com const char* fName; 69c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com HasherProc fHasher; 70c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} gRec[] = { 71c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com { "hasher0", hasher0 }, 7267a3271f0de9ccc32d559b042b862528272047ccmtklein { "hasher2", SkChecksum::Mix }, 73c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com}; 74c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 75c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com#define kMaxHashBits 12 76c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com#define kMaxHashCount (1 << kMaxHashBits) 77c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 78c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic int count_collisions(const uint16_t array[], int count, HasherProc proc, 79c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com unsigned hashMask) { 80c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com char table[kMaxHashCount]; 81c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com sk_bzero(table, sizeof(table)); 82a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 83c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int collisions = 0; 84c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (int i = 0; i < count; ++i) { 85c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int index = proc(array[i]) & hashMask; 86c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com collisions += table[index]; 87c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com table[index] = 1; 88c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 89c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return collisions; 90c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 91c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 92c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic void dump_array(const uint16_t array[], int count) { 93c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (int i = 0; i < count; ++i) { 94c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com SkDebugf(" %d,", array[i]); 95c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 96c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com SkDebugf("\n"); 97c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 98c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 99f168b86d7fafc5c20c87bebc6fd393cb17e120catfarinaclass FontCacheEfficiency : public Benchmark { 100c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.compublic: 101410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com FontCacheEfficiency() { 1022880df2609eba09b555ca37be04b6ad89290c765Tom Hudson if (false) dump_array(nullptr, 0); 103c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com if (false) rotr(0, 0); 104c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 105a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 106c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comprotected: 10736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* onGetName() override { 108c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return "fontefficiency"; 109c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 110a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 1112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson void onDraw(int loops, SkCanvas* canvas) override { 112c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com static bool gDone; 113c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com if (gDone) { 114c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return; 115c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 116c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com gDone = true; 1178af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 118c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (int hashBits = 6; hashBits <= 12; hashBits += 1) { 119c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int hashMask = ((1 << hashBits) - 1); 120c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (int limit = 32; limit <= 1024; limit <<= 1) { 121c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 122c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int collisions = 0; 123c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int glyphs = 0; 124c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com const uint16_t* array = gUniqueGlyphIDs; 125c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com while (*array != gUniqueGlyphIDs_Sentinel) { 126c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int count = SkMin32(count_glyphs(array), limit); 127c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com collisions += count_collisions(array, count, gRec[i].fHasher, hashMask); 128c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com glyphs += count; 129c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com array += count + 1; // skip the sentinel 130c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 131c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com SkDebugf("hashBits [%d] limit [%d] collisions [%d / %d = %1.2g%%] using %s\n", hashBits, limit, collisions, glyphs, 132c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com collisions * 100.0 / glyphs, gRec[i].fName); 133c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 134c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 135c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 136c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 137a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 1388af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.comprivate: 139f168b86d7fafc5c20c87bebc6fd393cb17e120catfarina typedef Benchmark INHERITED; 1408af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com}; 1418af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 1428af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com/////////////////////////////////////////////////////////////////////////////// 1438af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 144410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.comDEF_BENCH( return new FontCacheBench(); ) 145c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 146c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com// undefine this to run the efficiency test 147410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com//DEF_BENCH( return new FontCacheEfficiency(); ) 148