FontCacheBench.cpp revision 67a3271f0de9ccc32d559b042b862528272047cc
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 "SkFontHost.h" 128af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com#include "SkPaint.h" 138af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com#include "SkString.h" 148af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com#include "SkTemplates.h" 158af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 16664621a19e7ca5236ae4fce19e3ffd97f047b64dreed@google.com#include "gUniqueGlyphIDs.h" 17c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com#define gUniqueGlyphIDs_Sentinel 0xFFFF 188af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 19c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic int count_glyphs(const uint16_t start[]) { 20c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com const uint16_t* curr = start; 21c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com while (*curr != gUniqueGlyphIDs_Sentinel) { 22c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com curr += 1; 238af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 248b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com return static_cast<int>(curr - start); 25c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 268af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 27f168b86d7fafc5c20c87bebc6fd393cb17e120catfarinaclass FontCacheBench : public Benchmark { 28c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.compublic: 29410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com FontCacheBench() {} 30a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 318af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.comprotected: 328af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com virtual const char* onGetName() SK_OVERRIDE { 338af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com return "fontcache"; 348af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 35a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 363361471a3504ecd0351ff70f4c42d8d6fee963d4commit-bot@chromium.org virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { 378af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com SkPaint paint; 388af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com this->setupPaint(&paint); 398af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 40a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 412fef6d2bda33b348133843e22c1009504c6fc209reed@google.com const uint16_t* array = gUniqueGlyphIDs; 42c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com while (*array != gUniqueGlyphIDs_Sentinel) { 438b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com int count = count_glyphs(array); 443361471a3504ecd0351ff70f4c42d8d6fee963d4commit-bot@chromium.org for (int i = 0; i < loops; ++i) { 45c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com paint.measureText(array, count * sizeof(uint16_t)); 468af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 47c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com array += count + 1; // skip the sentinel 488af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 498af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com } 50a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 51c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comprivate: 52f168b86d7fafc5c20c87bebc6fd393cb17e120catfarina typedef Benchmark INHERITED; 53c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com}; 54c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 55c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com/////////////////////////////////////////////////////////////////////////////// 56c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 57c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic uint32_t rotr(uint32_t value, unsigned bits) { 58c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return (value >> bits) | (value << (32 - bits)); 59c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 60c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 61c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comtypedef uint32_t (*HasherProc)(uint32_t); 62c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 63c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic uint32_t hasher0(uint32_t value) { 64c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com value = value ^ (value >> 16); 65c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return value ^ (value >> 8); 66c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 67c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 68c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic const struct { 69c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com const char* fName; 70c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com HasherProc fHasher; 71c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} gRec[] = { 72c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com { "hasher0", hasher0 }, 7367a3271f0de9ccc32d559b042b862528272047ccmtklein { "hasher2", SkChecksum::Mix }, 74c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com}; 75c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 76c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com#define kMaxHashBits 12 77c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com#define kMaxHashCount (1 << kMaxHashBits) 78c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 79c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic int count_collisions(const uint16_t array[], int count, HasherProc proc, 80c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com unsigned hashMask) { 81c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com char table[kMaxHashCount]; 82c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com sk_bzero(table, sizeof(table)); 83a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 84c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int collisions = 0; 85c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (int i = 0; i < count; ++i) { 86c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int index = proc(array[i]) & hashMask; 87c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com collisions += table[index]; 88c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com table[index] = 1; 89c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 90c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return collisions; 91c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 92c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 93c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comstatic void dump_array(const uint16_t array[], int count) { 94c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (int i = 0; i < count; ++i) { 95c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com SkDebugf(" %d,", array[i]); 96c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 97c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com SkDebugf("\n"); 98c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com} 99c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 100f168b86d7fafc5c20c87bebc6fd393cb17e120catfarinaclass FontCacheEfficiency : public Benchmark { 101c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.compublic: 102410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com FontCacheEfficiency() { 103c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com if (false) dump_array(NULL, 0); 104c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com if (false) rotr(0, 0); 105c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 106a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 107c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.comprotected: 108c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com virtual const char* onGetName() SK_OVERRIDE { 109c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return "fontefficiency"; 110c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 111a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 1123361471a3504ecd0351ff70f4c42d8d6fee963d4commit-bot@chromium.org virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE { 113c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com static bool gDone; 114c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com if (gDone) { 115c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com return; 116c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 117c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com gDone = true; 1188af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 119c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (int hashBits = 6; hashBits <= 12; hashBits += 1) { 120c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int hashMask = ((1 << hashBits) - 1); 121c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (int limit = 32; limit <= 1024; limit <<= 1) { 122c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 123c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int collisions = 0; 124c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int glyphs = 0; 125c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com const uint16_t* array = gUniqueGlyphIDs; 126c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com while (*array != gUniqueGlyphIDs_Sentinel) { 127c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com int count = SkMin32(count_glyphs(array), limit); 128c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com collisions += count_collisions(array, count, gRec[i].fHasher, hashMask); 129c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com glyphs += count; 130c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com array += count + 1; // skip the sentinel 131c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 132c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com SkDebugf("hashBits [%d] limit [%d] collisions [%d / %d = %1.2g%%] using %s\n", hashBits, limit, collisions, glyphs, 133c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com collisions * 100.0 / glyphs, gRec[i].fName); 134c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 135c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 136c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 137c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com } 138a707fd53f779843cf9354db27589bb0ef6cb1a0bskia.committer@gmail.com 1398af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.comprivate: 140f168b86d7fafc5c20c87bebc6fd393cb17e120catfarina typedef Benchmark INHERITED; 1418af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com}; 1428af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 1438af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com/////////////////////////////////////////////////////////////////////////////// 1448af0371fe22e166daae1eec3cc75f1a0e69228bereed@google.com 145410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.comDEF_BENCH( return new FontCacheBench(); ) 146c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com 147c26523067a42b7033b0be9150c1f79eb9cae4ce8reed@google.com// undefine this to run the efficiency test 148410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com//DEF_BENCH( return new FontCacheEfficiency(); ) 149