• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 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 "SkTypes.h"
9 
10 #include "Benchmark.h"
11 #include "GrMemoryPool.h"
12 #include "SkRandom.h"
13 #include "SkTDArray.h"
14 #include "SkTemplates.h"
15 
16 #include <new>
17 
18 // change this to 0 to compare GrMemoryPool to default new / delete
19 #define OVERRIDE_NEW    1
20 
21 struct A {
22     int gStuff[10];
23 #if OVERRIDE_NEW
operator newA24     void* operator new (size_t size) { return gBenchPool.allocate(size); }
operator deleteA25     void operator delete (void* mem) { if (mem) { return gBenchPool.release(mem); } }
26 #endif
27     static GrMemoryPool gBenchPool;
28 };
29 GrMemoryPool A::gBenchPool(10 * (1 << 10), 10 * (1 << 10));
30 
31 /**
32  * This benchmark creates and deletes objects in stack order
33  */
34 class GrMemoryPoolBenchStack : public Benchmark {
35 public:
isSuitableFor(Backend backend)36     bool isSuitableFor(Backend backend) override {
37         return backend == kNonRendering_Backend;
38     }
39 
40 protected:
onGetName()41     const char* onGetName() override {
42         return "grmemorypool_stack";
43     }
44 
onDraw(int loops,SkCanvas *)45     void onDraw(int loops, SkCanvas*) override {
46         SkRandom r;
47         enum {
48             kMaxObjects = 4 * (1 << 10),
49         };
50         A* objects[kMaxObjects];
51 
52         // We delete if a random number [-1, 1] is < the thresh. Otherwise,
53         // we allocate. We start allocate-biased and ping-pong to delete-biased
54         SkScalar delThresh = -SK_ScalarHalf;
55         const int kSwitchThreshPeriod = loops / (2 * kMaxObjects);
56         int s = 0;
57 
58         int count = 0;
59         for (int i = 0; i < loops; i++, ++s) {
60             if (kSwitchThreshPeriod == s) {
61                 delThresh = -delThresh;
62                 s = 0;
63             }
64             SkScalar del = r.nextSScalar1();
65             if (count &&
66                 (kMaxObjects == count || del < delThresh)) {
67                 delete objects[count-1];
68                 --count;
69             } else {
70                 objects[count] = new A;
71                 ++count;
72             }
73         }
74         for (int i = 0; i < count; ++i) {
75             delete objects[i];
76         }
77     }
78 
79 private:
80     typedef Benchmark INHERITED;
81 };
82 
83 struct B {
84     int gStuff[10];
85 #if OVERRIDE_NEW
operator newB86     void* operator new (size_t size) { return gBenchPool.allocate(size); }
operator deleteB87     void operator delete (void* mem) { if (mem) { return gBenchPool.release(mem); } }
88 #endif
89     static GrMemoryPool gBenchPool;
90 };
91 GrMemoryPool B::gBenchPool(10 * (1 << 10), 10 * (1 << 10));
92 
93 /**
94  * This benchmark creates objects and deletes them in random order
95  */
96 class GrMemoryPoolBenchRandom : public Benchmark {
97 public:
isSuitableFor(Backend backend)98     bool isSuitableFor(Backend backend) override {
99         return backend == kNonRendering_Backend;
100     }
101 
102 protected:
onGetName()103     const char* onGetName() override {
104         return "grmemorypool_random";
105     }
106 
onDraw(int loops,SkCanvas *)107     void onDraw(int loops, SkCanvas*) override {
108         SkRandom r;
109         enum {
110             kMaxObjects = 4 * (1 << 10),
111         };
112         std::unique_ptr<B> objects[kMaxObjects];
113 
114         for (int i = 0; i < loops; i++) {
115             uint32_t idx = r.nextRangeU(0, kMaxObjects-1);
116             if (nullptr == objects[idx].get()) {
117                 objects[idx].reset(new B);
118             } else {
119                 objects[idx].reset();
120             }
121         }
122     }
123 
124 private:
125     typedef Benchmark INHERITED;
126 };
127 
128 struct C {
129     int gStuff[10];
130 #if OVERRIDE_NEW
operator newC131     void* operator new (size_t size) { return gBenchPool.allocate(size); }
operator deleteC132     void operator delete (void* mem) { if (mem) { return gBenchPool.release(mem); } }
133 #endif
134     static GrMemoryPool gBenchPool;
135 };
136 GrMemoryPool C::gBenchPool(10 * (1 << 10), 10 * (1 << 10));
137 
138 /**
139  * This benchmark creates objects and deletes them in queue order
140  */
141 class GrMemoryPoolBenchQueue : public Benchmark {
142     enum {
143         M = 4 * (1 << 10),
144     };
145 public:
isSuitableFor(Backend backend)146     bool isSuitableFor(Backend backend) override {
147         return backend == kNonRendering_Backend;
148     }
149 
150 protected:
onGetName()151     const char* onGetName() override {
152         return "grmemorypool_queue";
153     }
154 
onDraw(int loops,SkCanvas *)155     void onDraw(int loops, SkCanvas*) override {
156         SkRandom r;
157         C* objects[M];
158         for (int i = 0; i < loops; i++) {
159             uint32_t count = r.nextRangeU(0, M-1);
160             for (uint32_t i = 0; i < count; i++) {
161                 objects[i] = new C;
162             }
163             for (uint32_t i = 0; i < count; i++) {
164                 delete objects[i];
165             }
166         }
167     }
168 
169 private:
170     typedef Benchmark INHERITED;
171 };
172 
173 ///////////////////////////////////////////////////////////////////////////////
174 
175 DEF_BENCH( return new GrMemoryPoolBenchStack(); )
176 DEF_BENCH( return new GrMemoryPoolBenchRandom(); )
177 DEF_BENCH( return new GrMemoryPoolBenchQueue(); )
178