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 [-1, 1] fixed pt is < the thresh. Otherwise, 54 // we allocate. We start allocate-biased and ping-pong to delete-biased 55 SkFixed delThresh = -SK_FixedHalf; 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 SkFixed del = r.nextSFixed1(); 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 SkAutoTDelete<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].free(); 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