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