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