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 
10 #include "GrContext.h"
11 #include "GrContextPriv.h"
12 #include "GrGpu.h"
13 #include "GrGpuResource.h"
14 #include "GrGpuResourcePriv.h"
15 #include "GrResourceCache.h"
16 #include "SkCanvas.h"
17 
18 enum {
19     CACHE_SIZE_COUNT = 4096,
20 };
21 
22 class BenchResource : public GrGpuResource {
23 public:
BenchResource(GrGpu * gpu)24     BenchResource (GrGpu* gpu)
25         : INHERITED(gpu) {
26         this->registerWithCache(SkBudgeted::kYes);
27     }
28 
ComputeKey(int i,int keyData32Count,GrUniqueKey * key)29     static void ComputeKey(int i, int keyData32Count, GrUniqueKey* key) {
30         static GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
31         GrUniqueKey::Builder builder(key, kDomain, keyData32Count);
32         for (int j = 0; j < keyData32Count; ++j) {
33             builder[j] = i + j;
34         }
35     }
36 
37 private:
onGpuMemorySize() const38     size_t onGpuMemorySize() const override { return 100; }
getResourceType() const39     const char* getResourceType() const override { return "bench"; }
40     typedef GrGpuResource INHERITED;
41 };
42 
populate_cache(GrGpu * gpu,int resourceCount,int keyData32Count)43 static void populate_cache(GrGpu* gpu, int resourceCount, int keyData32Count) {
44     for (int i = 0; i < resourceCount; ++i) {
45         GrUniqueKey key;
46         BenchResource::ComputeKey(i, keyData32Count, &key);
47         GrGpuResource* resource = new BenchResource(gpu);
48         resource->resourcePriv().setUniqueKey(key);
49         resource->unref();
50     }
51 }
52 
53 class GrResourceCacheBenchAdd : public Benchmark {
54 public:
GrResourceCacheBenchAdd(int keyData32Count)55     GrResourceCacheBenchAdd(int keyData32Count)
56         : fFullName("grresourcecache_add")
57         , fKeyData32Count(keyData32Count) {
58         if (keyData32Count > 1) {
59             fFullName.appendf("_%d", fKeyData32Count);
60         }
61     }
62 
isSuitableFor(Backend backend)63     bool isSuitableFor(Backend backend) override {
64         return backend == kNonRendering_Backend;
65     }
66 protected:
onGetName()67     const char* onGetName() override {
68         return fFullName.c_str();
69     }
70 
onDraw(int loops,SkCanvas * canvas)71     void onDraw(int loops, SkCanvas* canvas) override {
72         sk_sp<GrContext> context(GrContext::MakeMock(nullptr));
73         if (nullptr == context) {
74             return;
75         }
76         // Set the cache budget to be very large so no purging occurs.
77         context->setResourceCacheLimits(CACHE_SIZE_COUNT, 1 << 30);
78 
79         GrResourceCache* cache = context->priv().getResourceCache();
80 
81         // Make sure the cache is empty.
82         cache->purgeAllUnlocked();
83         SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
84 
85         GrGpu* gpu = context->priv().getGpu();
86 
87         for (int i = 0; i < loops; ++i) {
88             populate_cache(gpu, CACHE_SIZE_COUNT, fKeyData32Count);
89             SkASSERT(CACHE_SIZE_COUNT == cache->getResourceCount());
90         }
91     }
92 
93 private:
94     SkString fFullName;
95     int fKeyData32Count;
96     typedef Benchmark INHERITED;
97 };
98 
99 class GrResourceCacheBenchFind : public Benchmark {
100 public:
GrResourceCacheBenchFind(int keyData32Count)101     GrResourceCacheBenchFind(int keyData32Count)
102         : fFullName("grresourcecache_find")
103         , fKeyData32Count(keyData32Count) {
104         if (keyData32Count > 1) {
105             fFullName.appendf("_%d", fKeyData32Count);
106         }
107     }
108 
isSuitableFor(Backend backend)109     bool isSuitableFor(Backend backend) override {
110         return backend == kNonRendering_Backend;
111     }
112 protected:
onGetName()113     const char* onGetName() override {
114         return fFullName.c_str();
115     }
116 
onDelayedSetup()117     void onDelayedSetup() override {
118         fContext = GrContext::MakeMock(nullptr);
119         if (!fContext) {
120             return;
121         }
122         // Set the cache budget to be very large so no purging occurs.
123         fContext->setResourceCacheLimits(CACHE_SIZE_COUNT, 1 << 30);
124 
125         GrResourceCache* cache = fContext->priv().getResourceCache();
126 
127         // Make sure the cache is empty.
128         cache->purgeAllUnlocked();
129         SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
130 
131         GrGpu* gpu = fContext->priv().getGpu();
132 
133         populate_cache(gpu, CACHE_SIZE_COUNT, fKeyData32Count);
134     }
135 
onDraw(int loops,SkCanvas * canvas)136     void onDraw(int loops, SkCanvas* canvas) override {
137         if (!fContext) {
138             return;
139         }
140         GrResourceCache* cache = fContext->priv().getResourceCache();
141         SkASSERT(CACHE_SIZE_COUNT == cache->getResourceCount());
142         for (int i = 0; i < loops; ++i) {
143             for (int k = 0; k < CACHE_SIZE_COUNT; ++k) {
144                 GrUniqueKey key;
145                 BenchResource::ComputeKey(k, fKeyData32Count, &key);
146                 sk_sp<GrGpuResource> resource(cache->findAndRefUniqueResource(key));
147                 SkASSERT(resource);
148             }
149         }
150     }
151 
152 private:
153     sk_sp<GrContext> fContext;
154     SkString fFullName;
155     int fKeyData32Count;
156     typedef Benchmark INHERITED;
157 };
158 
159 DEF_BENCH( return new GrResourceCacheBenchAdd(1); )
160 #ifdef SK_RELEASE
161 // Only on release because on debug the SkTDynamicHash validation is too slow.
162 DEF_BENCH( return new GrResourceCacheBenchAdd(2); )
163 DEF_BENCH( return new GrResourceCacheBenchAdd(3); )
164 DEF_BENCH( return new GrResourceCacheBenchAdd(4); )
165 DEF_BENCH( return new GrResourceCacheBenchAdd(5); )
166 DEF_BENCH( return new GrResourceCacheBenchAdd(10); )
167 DEF_BENCH( return new GrResourceCacheBenchAdd(25); )
168 DEF_BENCH( return new GrResourceCacheBenchAdd(54); )
169 DEF_BENCH( return new GrResourceCacheBenchAdd(55); )
170 DEF_BENCH( return new GrResourceCacheBenchAdd(56); )
171 #endif
172 
173 DEF_BENCH( return new GrResourceCacheBenchFind(1); )
174 #ifdef SK_RELEASE
175 DEF_BENCH( return new GrResourceCacheBenchFind(2); )
176 DEF_BENCH( return new GrResourceCacheBenchFind(3); )
177 DEF_BENCH( return new GrResourceCacheBenchFind(4); )
178 DEF_BENCH( return new GrResourceCacheBenchFind(5); )
179 DEF_BENCH( return new GrResourceCacheBenchFind(10); )
180 DEF_BENCH( return new GrResourceCacheBenchFind(25); )
181 DEF_BENCH( return new GrResourceCacheBenchFind(54); )
182 DEF_BENCH( return new GrResourceCacheBenchFind(55); )
183 DEF_BENCH( return new GrResourceCacheBenchFind(56); )
184 #endif
185