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