158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/* 258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Copyright 2013 Google Inc. 358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * 458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * found in the LICENSE file. 658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */ 758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkBenchmark.h" 958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkCanvas.h" 1058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkFontHost.h" 1158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkPaint.h" 1258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkString.h" 1358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkTemplates.h" 1458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 1558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "gUniqueGlyphIDs.h" 1658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#define gUniqueGlyphIDs_Sentinel 0xFFFF 1758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 1858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic int count_glyphs(const uint16_t start[]) { 1958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const uint16_t* curr = start; 2058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger while (*curr != gUniqueGlyphIDs_Sentinel) { 2158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger curr += 1; 2258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 2358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return curr - start; 2458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 2558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 2658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerclass FontCacheBench : public SkBenchmark { 2758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger enum { 2858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger N = SkBENCHLOOP(50) 2958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger }; 3058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 3158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerpublic: 3258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger FontCacheBench(void* param) : INHERITED(param) {} 3358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 3458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerprotected: 3558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger virtual const char* onGetName() SK_OVERRIDE { 3658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return "fontcache"; 3758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 3858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 3958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 4058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkPaint paint; 4158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger this->setupPaint(&paint); 4258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 4358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 4458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const uint16_t* array = gUniqueGlyphIDs; 4558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger while (*array != gUniqueGlyphIDs_Sentinel) { 4658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger size_t count = count_glyphs(array); 4758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for (int i = 0; i < N; ++i) { 4858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger paint.measureText(array, count * sizeof(uint16_t)); 4958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 5058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger array += count + 1; // skip the sentinel 5158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 5258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 5358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 5458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerprivate: 5558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger typedef SkBenchmark INHERITED; 5658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}; 5758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 5858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 5958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 6058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic uint32_t rotr(uint32_t value, unsigned bits) { 6158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return (value >> bits) | (value << (32 - bits)); 6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 6358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 6458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergertypedef uint32_t (*HasherProc)(uint32_t); 6558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 6658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic uint32_t hasher0(uint32_t value) { 6758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger value = value ^ (value >> 16); 6858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return value ^ (value >> 8); 6958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 7058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 7158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic uint32_t hasher2(uint32_t h) { 7258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger h ^= h >> 16; 7358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger h *= 0x85ebca6b; 7458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger h ^= h >> 13; 7558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger h *= 0xc2b2ae35; 7658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger h ^= h >> 16; 7758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 7858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger h ^= (h >> 8); 7958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return h; 8058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 8158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 8258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic const struct { 8358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const char* fName; 8458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger HasherProc fHasher; 8558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} gRec[] = { 8658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger { "hasher0", hasher0 }, 8758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger { "hasher2", hasher2 }, 8858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}; 8958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 9058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#define kMaxHashBits 12 9158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#define kMaxHashCount (1 << kMaxHashBits) 9258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 9358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic int count_collisions(const uint16_t array[], int count, HasherProc proc, 9458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger unsigned hashMask) { 9558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger char table[kMaxHashCount]; 9658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger sk_bzero(table, sizeof(table)); 9758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 9858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int collisions = 0; 9958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for (int i = 0; i < count; ++i) { 10058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int index = proc(array[i]) & hashMask; 10158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger collisions += table[index]; 10258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger table[index] = 1; 10358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 10458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return collisions; 10558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 10658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 10758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void dump_array(const uint16_t array[], int count) { 10858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for (int i = 0; i < count; ++i) { 10958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkDebugf(" %d,", array[i]); 11058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 11158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkDebugf("\n"); 11258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 11358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 11458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerclass FontCacheEfficiency : public SkBenchmark { 11558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerpublic: 11658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger FontCacheEfficiency(void* param) : INHERITED(param) { 11758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (false) dump_array(NULL, 0); 11858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (false) rotr(0, 0); 11958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 12058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 12158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerprotected: 12258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger virtual const char* onGetName() SK_OVERRIDE { 12358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return "fontefficiency"; 12458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger static bool gDone; 12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (gDone) { 12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return; 13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger gDone = true; 13258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 13358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for (int hashBits = 6; hashBits <= 12; hashBits += 1) { 13458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int hashMask = ((1 << hashBits) - 1); 13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for (int limit = 32; limit <= 1024; limit <<= 1) { 13658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int collisions = 0; 13858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int glyphs = 0; 13958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const uint16_t* array = gUniqueGlyphIDs; 14058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger while (*array != gUniqueGlyphIDs_Sentinel) { 14158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int count = SkMin32(count_glyphs(array), limit); 14258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger collisions += count_collisions(array, count, gRec[i].fHasher, hashMask); 14358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger glyphs += count; 14458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger array += count + 1; // skip the sentinel 14558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 14658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkDebugf("hashBits [%d] limit [%d] collisions [%d / %d = %1.2g%%] using %s\n", hashBits, limit, collisions, glyphs, 14758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger collisions * 100.0 / glyphs, gRec[i].fName); 14858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 14958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 15058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 15158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 15258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 15358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerprivate: 15458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger typedef SkBenchmark INHERITED; 15558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}; 15658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 15758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 15858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 15958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerDEF_BENCH( return new FontCacheBench(p); ) 16058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 16158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger// undefine this to run the efficiency test 16258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger//DEF_BENCH( return new FontCacheEfficiency(p); ) 163