1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2013 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Benchmark.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkChecksum.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTemplates.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gUniqueGlyphIDs.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define gUniqueGlyphIDs_Sentinel 0xFFFF 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int count_glyphs(const uint16_t start[]) { 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint16_t* curr = start; 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (*curr != gUniqueGlyphIDs_Sentinel) { 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot curr += 1; 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return static_cast<int>(curr - start); 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass FontCacheBench : public Benchmark { 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FontCacheBench() {} 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* onGetName() override { 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return "fontcache"; 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void onDraw(int loops, SkCanvas* canvas) override { 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paint; 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->setupPaint(&paint); 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint16_t* array = gUniqueGlyphIDs; 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (*array != gUniqueGlyphIDs_Sentinel) { 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = count_glyphs(array); 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < loops; ++i) { 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.measureText(array, count * sizeof(uint16_t)); 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot array += count + 1; // skip the sentinel 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef Benchmark INHERITED; 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic uint32_t rotr(uint32_t value, unsigned bits) { 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (value >> bits) | (value << (32 - bits)); 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottypedef uint32_t (*HasherProc)(uint32_t); 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic uint32_t hasher0(uint32_t value) { 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot value = value ^ (value >> 16); 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return value ^ (value >> 8); 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const struct { 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* fName; 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot HasherProc fHasher; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} gRec[] = { 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "hasher0", hasher0 }, 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "hasher2", SkChecksum::Mix }, 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define kMaxHashBits 12 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define kMaxHashCount (1 << kMaxHashBits) 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int count_collisions(const uint16_t array[], int count, HasherProc proc, 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned hashMask) { 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char table[kMaxHashCount]; 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(table, sizeof(table)); 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int collisions = 0; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; ++i) { 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int index = proc(array[i]) & hashMask; 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot collisions += table[index]; 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot table[index] = 1; 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return collisions; 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void dump_array(const uint16_t array[], int count) { 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; ++i) { 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf(" %d,", array[i]); 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("\n"); 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass FontCacheEfficiency : public Benchmark { 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FontCacheEfficiency() { 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (false) dump_array(nullptr, 0); 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (false) rotr(0, 0); 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* onGetName() override { 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return "fontefficiency"; 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void onDraw(int loops, SkCanvas* canvas) override { 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static bool gDone; 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (gDone) { 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gDone = true; 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int hashBits = 6; hashBits <= 12; hashBits += 1) { 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int hashMask = ((1 << hashBits) - 1); 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int limit = 32; limit <= 1024; limit <<= 1) { 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int collisions = 0; 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int glyphs = 0; 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const uint16_t* array = gUniqueGlyphIDs; 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (*array != gUniqueGlyphIDs_Sentinel) { 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = SkMin32(count_glyphs(array), limit); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot collisions += count_collisions(array, count, gRec[i].fHasher, hashMask); 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyphs += count; 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot array += count + 1; // skip the sentinel 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("hashBits [%d] limit [%d] collisions [%d / %d = %1.2g%%] using %s\n", hashBits, limit, collisions, glyphs, 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot collisions * 100.0 / glyphs, gRec[i].fName); 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef Benchmark INHERITED; 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_BENCH( return new FontCacheBench(); ) 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// undefine this to run the efficiency test 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//DEF_BENCH( return new FontCacheEfficiency(); ) 148