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