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