Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: third_party/WebKit/Source/wtf/SetPerfTest.cpp

Issue 2396533004: Introduce a FlatMap and FlatSet into WTF (Closed)
Patch Set: Add missing ostream override Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/wtf/FlatTable.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <array>
6 #include <set>
7 #include <unordered_set>
8
9 #include "base/bind.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "wtf/FlatSet.h"
12 #include "wtf/HashSet.h"
13
14 using testing::Values;
15
16 template <>
17 inline std::string testing::internal::GetTypeName<std::set<int>>() {
18 return "std::set";
19 }
20
21 template <>
22 inline std::string testing::internal::GetTypeName<std::unordered_set<int>>() {
23 return "std::unordered_set";
24 }
25
26 template <>
27 inline std::string testing::internal::GetTypeName<WTF::FlatSet<int>>() {
28 return "WTF::FlatSet";
29 }
30
31 template <>
32 inline std::string testing::internal::GetTypeName<WTF::HashSet<int>>() {
33 return "WTF::HashSet";
34 }
35
36 using AssociativeSetTypes = testing::Types<std::set<int>, WTF::FlatSet<int>>;
37 using SetTypes = testing::Types<std::set<int>,
38 std::unordered_set<int>,
39 WTF::FlatSet<int>,
40 WTF::HashSet<int>>;
41
42 namespace WTF {
43
44 class Benchmark : public testing::Test {
45 public:
46 Benchmark() {}
47 virtual ~Benchmark() {}
48
49 enum {
50 kBestOfNRuns = 10,
51 kNumPermutedInts = 1 << 15,
52 };
53
54 static void SetUpTestCase() {
55 for (size_t i = 0; i < permuted_ints_.size(); i++)
56 permuted_ints_[i] = i + 1; // WTF::HashSet doesn't like adding 0.
57
58 // Apply a pseudo random permutation.
59 int32_t num = 1234;
60 for (size_t i = 0; i < permuted_ints_.size(); i++) {
61 num = static_cast<int32_t>((num * 16807) % 2147483647L);
62 std::swap(permuted_ints_[i], permuted_ints_[num % permuted_ints_.size()]);
63 }
64 }
65
66 void RunBenchmarkSet(base::Callback<void(size_t)> init,
67 base::Callback<void(size_t)> run) {
68 for (size_t set_size : set_sizes_) {
69 double best_time = 0;
70 for (size_t i = 0; i < kBestOfNRuns; i++) {
71 double time = RunBenchmark(init, run, set_size);
72 if (i == 0) {
73 best_time = time;
74 } else if (time < best_time) {
75 best_time = time;
76 }
77 }
78 std::cout << "Set size " << set_size << " runtime (us) " << best_time
79 << std::endl;
80 }
81 }
82
83 static std::array<int, kNumPermutedInts> permuted_ints_;
84
85 private:
86 double RunBenchmark(base::Callback<void(size_t)> init,
87 base::Callback<void(size_t)> run,
88 size_t set_size) {
89 init.Run(set_size);
90 base::ThreadTicks start = base::ThreadTicks::Now();
91 base::ThreadTicks now;
92 unsigned long long num_iterations = 0;
93 do {
94 run.Run(set_size);
95 now = base::ThreadTicks::Now();
96 num_iterations++;
97 } while (now - start < base::TimeDelta::FromMilliseconds(100));
98 return (now - start).InMicroseconds() / static_cast<double>(num_iterations);
99 }
100
101 std::vector<size_t> set_sizes_ = {1, 2, 4, 8, 16, 32,
102 64, 128, 256, 512, 1024, 2048,
103 4096, 8192, 16384, 32768};
104 };
105
106 std::array<int, Benchmark::kNumPermutedInts> Benchmark::permuted_ints_;
107
108 template <typename SetType>
109 class SetBenchmark : public Benchmark {
110 public:
111 SetType set_;
112 size_t index_ = 0;
113 size_t run_ = 0;
114
115 void setClear() { set_.clear(); }
116
117 void setInsertUnique(int i) { setInsert(i); }
118
119 void setInsert(int i) { set_.insert(i); }
120
121 void setErase(int i) { set_.erase(i); }
122
123 void setEraseFront() { set_.erase(set_.begin()); }
124
125 void setEraseBack() { set_.erase(std::prev(set_.end())); }
126 };
127
128 template <>
129 void SetBenchmark<FlatSet<int>>::setInsertUnique(int i) {
130 set_.insertUnique(i);
131 }
132
133 template <>
134 void SetBenchmark<FlatSet<int>>::setEraseBack() {
135 set_.erase(set_.rbegin());
136 }
137
138 template <>
139 void SetBenchmark<HashSet<int>>::setInsert(int i) {
140 set_.add(i);
141 }
142
143 template <>
144 void SetBenchmark<HashSet<int>>::setErase(int i) {
145 set_.remove(i);
146 }
147
148 TYPED_TEST_CASE(SetBenchmark, SetTypes);
149
150 TYPED_TEST(SetBenchmark, InsertAndErasePseudoRandom) {
151 Benchmark::RunBenchmarkSet(
152 base::Bind([](SetBenchmark<TypeParam>* fixture,
153 size_t set_size) { fixture->setClear(); },
154 base::Unretained(this)),
155 base::Bind(
156 [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
157 const auto& permutation = Benchmark::permuted_ints_;
158 size_t& index = fixture->index_;
159
160 for (size_t i = 0; i < set_size; i++) {
161 fixture->setInsert(permutation[index++ % permutation.size()]);
162 }
163 for (size_t i = 0; i < set_size; i++) {
164 fixture->setErase(permutation[index++ % permutation.size()]);
165 }
166 },
167 base::Unretained(this)));
168 }
169
170 TYPED_TEST(SetBenchmark, InsertAndEraseOutsideIn) {
171 Benchmark::RunBenchmarkSet(
172 base::Bind([](SetBenchmark<TypeParam>* fixture,
173 size_t set_size) { fixture->set_.clear(); },
174 base::Unretained(this)),
175 base::Bind(
176 [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
177 for (size_t i = 1; i < set_size; i++) {
178 fixture->setInsertUnique(set_size - i);
179 fixture->setInsertUnique(set_size + i);
180 }
181 for (size_t i = set_size - 1; i > 0; i--) {
182 fixture->setErase(set_size - i);
183 fixture->setErase(set_size + i);
184 }
185 },
186 base::Unretained(this)));
187 }
188
189 TYPED_TEST(SetBenchmark, InsertAndEraseInsideOut) {
190 Benchmark::RunBenchmarkSet(
191 base::Bind([](SetBenchmark<TypeParam>* fixture,
192 size_t set_size) { fixture->set_.clear(); },
193 base::Unretained(this)),
194 base::Bind(
195 [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
196 for (size_t i = 1; i < set_size; i++) {
197 fixture->setInsertUnique(i);
198 fixture->setInsertUnique(set_size + set_size - i);
199 }
200 for (size_t i = set_size - 1; i > 0; i--) {
201 fixture->setErase(i);
202 fixture->setErase(set_size + set_size - i);
203 }
204 },
205 base::Unretained(this)));
206 }
207
208 TYPED_TEST(SetBenchmark, FixedSizeFind) {
209 size_t num = 0;
210 Benchmark::RunBenchmarkSet(
211 base::Bind(
212 [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
213 const auto& permutation = Benchmark::permuted_ints_;
214
215 fixture->setClear();
216 for (size_t i = 0; i < set_size; i++)
217 fixture->setInsert(permutation[i % permutation.size()]);
218 },
219 base::Unretained(this)),
220 base::Bind(
221 [](SetBenchmark<TypeParam>* fixture, size_t* num, size_t set_size) {
222 const auto& permutation = Benchmark::permuted_ints_;
223
224 for (size_t i = 0; i < set_size; i++) {
225 if (fixture->set_.find(permutation[i % permutation.size()]) !=
226 fixture->set_.end()) {
227 (*num)++; // Prevent the compiler from optimizing stuff away.
228 }
229 }
230 },
231 base::Unretained(this), base::Unretained(&num)));
232 }
233
234 template <typename SetType>
235 class AssociativeSetBenchmark : public SetBenchmark<SetType> {};
236
237 TYPED_TEST_CASE(AssociativeSetBenchmark, AssociativeSetTypes);
238
239 TYPED_TEST(AssociativeSetBenchmark, FixedSizeEraseAndInsert) {
240 Benchmark::RunBenchmarkSet(
241 base::Bind(
242 [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
243 const auto& permutation = Benchmark::permuted_ints_;
244 size_t& index = fixture->index_;
245
246 fixture->setClear();
247 for (index = 0; index < set_size; index++) {
248 fixture->setInsert(permutation[index % permutation.size()]);
249 }
250 },
251 base::Unretained(this)),
252 base::Bind(
253 [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
254 const auto& permutation = Benchmark::permuted_ints_;
255 size_t& index = fixture->index_;
256 size_t& run = fixture->run_; // Necessary to ensure uniqueness.
257
258 for (size_t i = 0; i < 10000; i++) {
259 fixture->setEraseFront();
260 fixture->setInsertUnique(
261 run + permutation[index++ % permutation.size()]);
262 }
263
264 run += permutation.size();
265 },
266 base::Unretained(this)));
267 }
268
269 TYPED_TEST(AssociativeSetBenchmark, InsertAndEraseOutsideIn) {
270 Benchmark::RunBenchmarkSet(
271 base::Bind([](SetBenchmark<TypeParam>* fixture,
272 size_t set_size) { fixture->set_.clear(); },
273 base::Unretained(this)),
274 base::Bind(
275 [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
276 for (size_t i = 1; i < set_size; i++) {
277 fixture->setInsertUnique(set_size - i);
278 fixture->setInsertUnique(set_size + i);
279 }
280 for (size_t i = set_size - 1; i > 0; i--) {
281 fixture->setEraseFront();
282 fixture->setEraseBack();
283 }
284 },
285 base::Unretained(this)));
286 EXPECT_TRUE(this->set_.empty());
287 }
288
289 } // namespace WTF
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/FlatTable.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698