StackBench.cpp revision 506ecc24bfbc5edc3e43830a9fbd815c3d6da96a
1/* 2 * Copyright 2014 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 "SkBenchmark.h" 9#include "SkRandom.h" 10 11#include "SkChunkAlloc.h" 12#include "SkDeque.h" 13#include "SkTArray.h" 14#include "SkTDArray.h" 15#include <vector> 16 17// This file has several benchmarks using various data structures to do stack-like things: 18// - push 19// - push, immediately pop 20// - push many, pop all of them 21// - serial access 22// - random access 23// When a data structure doesn't suppport an operation efficiently, we leave that combination out. 24// Where possible we hint to the data structure to allocate in 4K pages. 25// 26// These benchmarks may help you decide which data structure to use for a dynamically allocated 27// ordered list of allocations that grows on one end. 28// 29// Current overall winner (01/2014): SkTDArray. 30// It wins every benchmark on every machine I tried (Desktop, Nexus S, Laptop). 31 32template <typename Impl> 33struct StackBench : public SkBenchmark { 34 virtual bool isSuitableFor(Backend b) SK_OVERRIDE { return b == kNonRendering_Backend; } 35 virtual const char* onGetName() SK_OVERRIDE { return Impl::kName; } 36 virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE { Impl::bench(loops); } 37}; 38 39#define BENCH(name) \ 40 struct name { static const char* const kName; static void bench(int); }; \ 41 const char* const name::kName = #name; \ 42 DEF_BENCH(return new StackBench<name>();) \ 43 void name::bench(int loops) 44 45static const int K = 2049; 46 47// Add K items, then iterate through them serially many times. 48 49BENCH(Deque_Serial) { 50 SkDeque s(sizeof(int), 1024); 51 for (int i = 0; i < K; i++) *(int*)s.push_back() = i; 52 53 volatile int junk = 0; 54 for (int j = 0; j < loops; j++) { 55 SkDeque::Iter it(s, SkDeque::Iter::kFront_IterStart); 56 while(void* p = it.next()) { 57 junk += *(int*)p; 58 } 59 } 60} 61 62BENCH(TArray_Serial) { 63 SkTArray<int, true> s; 64 for (int i = 0; i < K; i++) s.push_back(i); 65 66 volatile int junk = 0; 67 for (int j = 0; j < loops; j++) { 68 for (int i = 0; i < s.count(); i++) junk += s[i]; 69 } 70} 71 72BENCH(TDArray_Serial) { 73 SkTDArray<int> s; 74 for (int i = 0; i < K; i++) s.push(i); 75 76 volatile int junk = 0; 77 for (int j = 0; j < loops; j++) { 78 for (int i = 0; i < s.count(); i++) junk += s[i]; 79 } 80} 81 82BENCH(vector_Serial) { 83 std::vector<int> s; 84 for (int i = 0; i < K; i++) s.push_back(i); 85 86 volatile int junk = 0; 87 for (int j = 0; j < loops; j++) { 88 for (size_t i = 0; i < s.size(); i++) junk += s[i]; 89 } 90} 91 92// Add K items, then randomly access them many times. 93 94BENCH(TArray_RandomAccess) { 95 SkTArray<int, true> s; 96 for (int i = 0; i < K; i++) s.push_back(i); 97 98 SkRandom rand; 99 volatile int junk = 0; 100 for (int i = 0; i < K*loops; i++) { 101 junk += s[rand.nextULessThan(K)]; 102 } 103} 104 105BENCH(TDArray_RandomAccess) { 106 SkTDArray<int> s; 107 for (int i = 0; i < K; i++) s.push(i); 108 109 SkRandom rand; 110 volatile int junk = 0; 111 for (int i = 0; i < K*loops; i++) { 112 junk += s[rand.nextULessThan(K)]; 113 } 114} 115 116BENCH(vector_RandomAccess) { 117 std::vector<int> s; 118 for (int i = 0; i < K; i++) s.push_back(i); 119 120 SkRandom rand; 121 volatile int junk = 0; 122 for (int i = 0; i < K*loops; i++) { 123 junk += s[rand.nextULessThan(K)]; 124 } 125} 126 127// Push many times. 128 129BENCH(ChunkAlloc_Push) { 130 SkChunkAlloc s(4096); 131 for (int i = 0; i < K*loops; i++) s.allocThrow(sizeof(int)); 132} 133 134BENCH(Deque_Push) { 135 SkDeque s(sizeof(int), 1024); 136 for (int i = 0; i < K*loops; i++) *(int*)s.push_back() = i; 137} 138 139BENCH(TArray_Push) { 140 SkTArray<int, true> s; 141 for (int i = 0; i < K*loops; i++) s.push_back(i); 142} 143 144BENCH(TDArray_Push) { 145 SkTDArray<int> s; 146 for (int i = 0; i < K*loops; i++) s.push(i); 147} 148 149BENCH(vector_Push) { 150 std::vector<int> s; 151 for (int i = 0; i < K*loops; i++) s.push_back(i); 152} 153 154// Push then immediately pop many times. 155 156BENCH(ChunkAlloc_PushPop) { 157 SkChunkAlloc s(4096); 158 for (int i = 0; i < K*loops; i++) { 159 void* p = s.allocThrow(sizeof(int)); 160 s.unalloc(p); 161 } 162} 163 164BENCH(Deque_PushPop) { 165 SkDeque s(sizeof(int), 1024); 166 for (int i = 0; i < K*loops; i++) { 167 *(int*)s.push_back() = i; 168 s.pop_back(); 169 } 170} 171 172BENCH(TArray_PushPop) { 173 SkTArray<int, true> s; 174 for (int i = 0; i < K*loops; i++) { 175 s.push_back(i); 176 s.pop_back(); 177 } 178} 179 180BENCH(TDArray_PushPop) { 181 SkTDArray<int> s; 182 for (int i = 0; i < K*loops; i++) { 183 s.push(i); 184 s.pop(); 185 } 186} 187 188BENCH(vector_PushPop) { 189 std::vector<int> s; 190 for (int i = 0; i < K*loops; i++) { 191 s.push_back(i); 192 s.pop_back(); 193 } 194} 195 196// Push many items, then pop them all. 197 198BENCH(Deque_PushAllPopAll) { 199 SkDeque s(sizeof(int), 1024); 200 for (int i = 0; i < K*loops; i++) *(int*)s.push_back() = i; 201 for (int i = 0; i < K*loops; i++) s.pop_back(); 202} 203 204BENCH(TArray_PushAllPopAll) { 205 SkTArray<int, true> s; 206 for (int i = 0; i < K*loops; i++) s.push_back(i); 207 for (int i = 0; i < K*loops; i++) s.pop_back(); 208} 209 210BENCH(TDArray_PushAllPopAll) { 211 SkTDArray<int> s; 212 for (int i = 0; i < K*loops; i++) s.push(i); 213 for (int i = 0; i < K*loops; i++) s.pop(); 214} 215 216BENCH(vector_PushAllPopAll) { 217 std::vector<int> s; 218 for (int i = 0; i < K*loops; i++) s.push_back(i); 219 for (int i = 0; i < K*loops; i++) s.pop_back(); 220} 221