proxygen
ConcurrentSkipListBenchmark.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 // @author: Xin Liu <xliux@fb.com>
17 
18 #include <map>
19 #include <memory>
20 #include <random>
21 #include <set>
22 #include <thread>
23 
24 #include <folly/Benchmark.h>
26 #include <folly/hash/Hash.h>
29 #include <glog/logging.h>
30 
31 DEFINE_int32(num_threads, 12, "num concurrent threads to test");
32 
33 // In some case, we may want to test worker threads operating on multiple
34 // lists. For example in search, not all threads are visiting the same posting
35 // list, but for the ones with some popular terms, they do get multiple
36 // visitors at the same time.
37 DEFINE_int32(num_sets, 1, "num of set to operate on");
38 
39 static const int kInitHeadHeight = 10;
40 static const int kMaxValue = 0x1000000;
41 
42 namespace {
43 
44 using namespace folly;
45 
46 typedef int ValueType;
47 typedef ConcurrentSkipList<ValueType> SkipListType;
48 typedef SkipListType::Accessor SkipListAccessor;
49 typedef std::set<ValueType> SetType;
50 
51 static std::vector<ValueType> gData;
52 static void initData() {
53  gData.resize(kMaxValue);
54  for (int i = 0; i < kMaxValue; ++i) {
55  gData[i] = i;
56  }
57  std::shuffle(gData.begin(), gData.end(), std::mt19937{});
58 }
59 
60 // single thread benchmarks
61 void BM_IterateOverSet(int iters, int size) {
62  SetType a_set;
63 
65  CHECK_GT(size, 0);
66  for (int i = 0; i < size; ++i) {
67  a_set.insert(gData[rand() % kMaxValue]);
68  }
69  }
70 
71  int64_t sum = 0;
72  auto iter = a_set.begin();
73  for (int i = 0; i < iters; ++i) {
74  sum += *iter++;
75  if (iter == a_set.end()) {
76  iter = a_set.begin();
77  }
78  }
80  // VLOG(20) << "sum = " << sum;
81  }
82 }
83 
84 void BM_IterateSkipList(int iters, int size) {
85  BenchmarkSuspender susp;
86  CHECK_GT(size, 0);
87  auto skipList = SkipListType::create(kInitHeadHeight);
88  for (int i = 0; i < size; ++i) {
89  skipList.add(rand() % kMaxValue);
90  }
91  int64_t sum = 0;
92  susp.dismiss();
93 
94  auto iter = skipList.begin();
95  for (int i = 0; i < iters; ++i) {
96  sum += *iter++;
97  if (iter == skipList.end()) {
98  iter = skipList.begin();
99  }
100  }
101 
103  // VLOG(20) << "sum = " << sum;
104  }
105 }
106 
107 void BM_SetMerge(int iters, int size) {
108  BenchmarkSuspender susp;
109  SetType a_set;
110  SetType b_set;
111  for (int i = 0; i < iters; ++i) {
112  a_set.insert(rand() % kMaxValue);
113  }
114  for (int i = 0; i < size; ++i) {
115  b_set.insert(rand() % kMaxValue);
116  }
117  susp.dismiss();
118 
119  int64_t mergedSum = 0;
120  FOR_EACH (it, a_set) {
121  if (b_set.find(*it) != b_set.end()) {
122  mergedSum += *it;
123  }
124  }
126  // VLOG(20) << mergedSum;
127  }
128 }
129 
130 void BM_CSLMergeLookup(int iters, int size) {
131  BenchmarkSuspender susp;
132  auto skipList = SkipListType::create(kInitHeadHeight);
133  auto skipList2 = SkipListType::create(kInitHeadHeight);
134 
135  for (int i = 0; i < iters; ++i) {
136  skipList.add(rand() % kMaxValue);
137  }
138  for (int i = 0; i < size; ++i) {
139  skipList2.add(rand() % kMaxValue);
140  }
141  int64_t mergedSum = 0;
142  susp.dismiss();
143 
144  SkipListType::Skipper skipper(skipList2);
145  FOR_EACH (it, skipList) {
146  if (skipper.to(*it)) {
147  mergedSum += *it;
148  }
149  }
150 
152  // VLOG(20) << mergedSum;
153  }
154 }
155 
156 // merge by two skippers
157 void BM_CSLMergeIntersection(int iters, int size) {
158  BenchmarkSuspender susp;
159  auto skipList = SkipListType::create(kInitHeadHeight);
160  auto skipList2 = SkipListType::create(kInitHeadHeight);
161  for (int i = 0; i < iters; ++i) {
162  skipList.add(rand() % kMaxValue);
163  }
164  for (int i = 0; i < size; ++i) {
165  skipList2.add(rand() % kMaxValue);
166  }
167  susp.dismiss();
168 
169  SkipListType::Skipper s1(skipList);
170  SkipListType::Skipper s2(skipList2);
171 
172  int64_t mergedSum = 0;
173 
174  while (s1.good() && s2.good()) {
175  int v1 = s1.data();
176  int v2 = s2.data();
177  if (v1 < v2) {
178  s1.to(v2);
179  } else if (v1 > v2) {
180  s2.to(v1);
181  } else {
182  mergedSum += v1;
183  ++s1;
184  ++s2;
185  }
186  }
187 
189  // VLOG(20) << mergedSum;
190  }
191 }
192 
193 void BM_SetContainsNotFound(int iters, int size) {
194  BenchmarkSuspender susp;
195  SetType aset;
196  CHECK_LT(size, kMaxValue);
197  for (int i = 0; i < size; ++i) {
198  aset.insert(2 * i);
199  }
200  int64_t sum = 0;
201  susp.dismiss();
202 
203  for (int i = 0; i < iters; ++i) {
204  sum += (aset.end() == aset.find(2 * i + 1));
205  }
206 
208  // VLOG(20) << sum;
209  }
210 }
211 
212 void BM_SetContainsFound(int iters, int size) {
213  BenchmarkSuspender susp;
214  SetType aset;
215  CHECK_LT(size, kMaxValue);
216 
217  for (int i = 0; i < size; ++i) {
218  aset.insert(i);
219  }
220 
221  std::vector<int> values;
222  for (int i = 0; i < iters; ++i) {
223  values.push_back(rand() % size);
224  }
225  int64_t sum = 0;
226  susp.dismiss();
227 
228  for (int i = 0; i < iters; ++i) {
229  sum += (aset.end() == aset.find(values[i]));
230  }
231 
233  // VLOG(20) << sum;
234  }
235 }
236 
237 void BM_CSLContainsFound(int iters, int size) {
238  BenchmarkSuspender susp;
239  auto skipList = SkipListType::create(kInitHeadHeight);
240  CHECK_LT(size, kMaxValue);
241 
242  for (int i = 0; i < size; ++i) {
243  skipList.add(i);
244  }
245  std::vector<int> values;
246  for (int i = 0; i < iters; ++i) {
247  values.push_back(rand() % size);
248  }
249  int64_t sum = 0;
250  susp.dismiss();
251 
252  for (int i = 0; i < iters; ++i) {
253  sum += skipList.contains(values[i]);
254  }
255 
257  // VLOG(20) << sum;
258  }
259 }
260 
261 void BM_CSLContainsNotFound(int iters, int size) {
262  BenchmarkSuspender susp;
263  auto skipList = SkipListType::create(kInitHeadHeight);
264  CHECK_LT(size, kMaxValue);
265 
266  for (int i = 0; i < size; ++i) {
267  skipList.add(2 * i);
268  }
269  int64_t sum = 0;
270  susp.dismiss();
271 
272  for (int i = 0; i < iters; ++i) {
273  sum += skipList.contains(2 * i + 1);
274  }
275 
277  // VLOG(20) << sum;
278  }
279 }
280 
281 void BM_AddSet(int iters, int size) {
282  BenchmarkSuspender susp;
283  SetType aset;
284  for (int i = 0; i < size; ++i) {
285  aset.insert(gData[i]);
286  }
287  susp.dismiss();
288 
289  for (int i = size; i < size + iters; ++i) {
290  aset.insert(gData[i]);
291  }
292 }
293 
294 void BM_AddSkipList(int iters, int size) {
295  BenchmarkSuspender susp;
296  auto skipList = SkipListType::create(kInitHeadHeight);
297  for (int i = 0; i < size; ++i) {
298  skipList.add(gData[i]);
299  }
300  susp.dismiss();
301 
302  for (int i = size; i < size + iters; ++i) {
303  skipList.add(gData[i]);
304  }
305 }
306 
307 BENCHMARK(Accessor, iters) {
308  BenchmarkSuspender susp;
309  auto skiplist = SkipListType::createInstance(kInitHeadHeight);
310  auto sl = skiplist.get();
311 
312  susp.dismiss();
313  for (size_t i = 0; i < iters; ++i) {
314  SkipListAccessor accessor(sl);
315  }
316 }
317 
318 // a benchmark to estimate the
319 // low bound of doing a ref counting for an Accessor
320 BENCHMARK(accessorBasicRefcounting, iters) {
321  BenchmarkSuspender susp;
322  auto* value = new std::atomic<int32_t>();
323  auto* dirty = new std::atomic<int32_t>();
324  *value = *dirty = 0;
326  l.init();
327 
328  susp.dismiss();
329  for (size_t i = 0; i < iters; ++i) {
330  value->fetch_add(1, std::memory_order_relaxed);
331  if (dirty->load(std::memory_order_acquire) != 0) {
332  folly::MSLGuard g(l);
333  }
334  value->fetch_sub(1, std::memory_order_relaxed);
335  }
336 
338  delete dirty;
339  delete value;
340  }
341 }
342 
343 // Data For testing contention benchmark
344 class ConcurrentAccessData {
345  public:
346  explicit ConcurrentAccessData(int size)
347  : skipList_(SkipListType::create(10)),
348  sets_(FLAGS_num_sets),
349  locks_(FLAGS_num_sets) {
350  for (int i = 0; i < size; ++i) {
351  sets_[0].insert(i);
352  skipList_.add(i);
353  }
354 
355  for (int i = 0; i < FLAGS_num_sets; ++i) {
356  locks_[i] = new RWSpinLock();
357  if (i > 0) {
358  sets_[i] = sets_[0];
359  }
360  }
361 
362 // This requires knowledge of the C++ library internals. Only use it if we're
363 // using the GNU C++ library.
364 #ifdef _GLIBCXX_SYMVER
365  // memory usage
366  int64_t setMemorySize = sets_[0].size() * sizeof(*sets_[0].begin()._M_node);
367  int64_t cslMemorySize = 0;
368  for (auto it = skipList_.begin(); it != skipList_.end(); ++it) {
369  cslMemorySize += it.nodeSize();
370  }
371 
372  LOG(INFO) << "size=" << sets_[0].size()
373  << "; std::set memory size=" << setMemorySize
374  << "; csl memory size=" << cslMemorySize;
375 #endif
376 
377  readValues_.reserve(size);
378  deleteValues_.reserve(size);
379  writeValues_.reserve(size);
380  for (int i = size; i < 2 * size; ++i) {
381  readValues_.push_back(2 * i);
382  deleteValues_.push_back(2 * i);
383 
384  // half new values and half already in the list
385  writeValues_.push_back((rand() % 2) + 2 * i);
386  }
387  std::shuffle(readValues_.begin(), readValues_.end(), std::mt19937{});
388  std::shuffle(deleteValues_.begin(), deleteValues_.end(), std::mt19937{});
389  std::shuffle(writeValues_.begin(), writeValues_.end(), std::mt19937{});
390  }
391 
392  ~ConcurrentAccessData() {
393  FOR_EACH (lock, locks_)
394  delete *lock;
395  }
396 
397  inline bool skipListFind(int /* idx */, ValueType val) {
398  return skipList_.contains(val);
399  }
400  inline void skipListInsert(int /* idx */, ValueType val) {
401  skipList_.add(val);
402  }
403  inline void skipListErase(int /* idx */, ValueType val) {
404  skipList_.remove(val);
405  }
406 
407  inline bool setFind(int idx, ValueType val) {
408  RWSpinLock::ReadHolder g(locks_[idx]);
409  return sets_[idx].find(val) == sets_[idx].end();
410  }
411  inline void setInsert(int idx, ValueType val) {
412  RWSpinLock::WriteHolder g(locks_[idx]);
413  sets_[idx].insert(val);
414  }
415  inline void setErase(int idx, ValueType val) {
416  RWSpinLock::WriteHolder g(locks_[idx]);
417  sets_[idx].erase(val);
418  }
419 
420  void runSkipList(int id, size_t iters) {
421  int sum = 0;
422  for (size_t i = 0; i < iters; ++i) {
423  sum += accessSkipList(id, i);
424  }
425  // VLOG(20) << sum;
426  }
427 
428  void runSet(size_t id, size_t iters) {
429  int sum = 0;
430  for (size_t i = 0; i < iters; ++i) {
431  sum += accessSet(id, i);
432  }
433  // VLOG(20) << sum;
434  }
435 
436  bool accessSkipList(int64_t id, size_t t) {
437  if (t > readValues_.size()) {
438  t = t % readValues_.size();
439  }
441  switch (h % 8) {
442  case 7: // write
443  if ((h & 0x31) == 0) { // 1/4 chance to delete
444  skipListErase(0, deleteValues_[t]);
445  } else {
446  skipListInsert(0, writeValues_[t]);
447  }
448  return false;
449  default:
450  return skipListFind(0, readValues_[t]);
451  }
452  }
453 
454  bool accessSet(int64_t id, size_t t) {
455  if (t > readValues_.size()) {
456  t = t % readValues_.size();
457  }
459  int idx = (h % FLAGS_num_sets);
460  switch (h % 8) { // 1/8 chance to write
461  case 7: // write
462  if ((h & 0x31) == 0) { // 1/32 chance to delete
463  setErase(idx, deleteValues_[t]);
464  } else {
465  setInsert(idx, writeValues_[t]);
466  }
467  return false;
468  default:
469  return setFind(idx, readValues_[t]);
470  }
471  }
472 
473  private:
474  SkipListType::Accessor skipList_;
475  std::vector<SetType> sets_;
476  std::vector<RWSpinLock*> locks_;
477 
478  std::vector<ValueType> readValues_;
479  std::vector<ValueType> writeValues_;
480  std::vector<ValueType> deleteValues_;
481 };
482 
483 static std::map<int, std::shared_ptr<ConcurrentAccessData>> g_data;
484 
485 static ConcurrentAccessData* mayInitTestData(int size) {
486  auto it = g_data.find(size);
487  if (it == g_data.end()) {
488  auto ptr = std::make_shared<ConcurrentAccessData>(size);
489  g_data[size] = ptr;
490  return ptr.get();
491  }
492  return it->second.get();
493 }
494 
495 void BM_ContentionCSL(int iters, int size) {
496  BenchmarkSuspender susp;
497  auto data = mayInitTestData(size);
498  std::vector<std::thread> threads;
499  susp.dismiss();
500 
501  for (int i = 0; i < FLAGS_num_threads; ++i) {
502  threads.push_back(
503  std::thread(&ConcurrentAccessData::runSkipList, data, i, iters));
504  }
505  FOR_EACH (t, threads) { (*t).join(); }
506 }
507 
508 void BM_ContentionStdSet(int iters, int size) {
509  BenchmarkSuspender susp;
510  auto data = mayInitTestData(size);
511  std::vector<std::thread> threads;
512  susp.dismiss();
513 
514  for (int i = 0; i < FLAGS_num_threads; ++i) {
515  threads.push_back(
516  std::thread(&ConcurrentAccessData::runSet, data, i, iters));
517  }
518  FOR_EACH (t, threads) { (*t).join(); }
519  susp.rehire();
520 }
521 
522 // Single-thread benchmarking
523 
525 
526 BENCHMARK_PARAM(BM_IterateOverSet, 1000)
527 BENCHMARK_PARAM(BM_IterateSkipList, 1000)
529 BENCHMARK_PARAM(BM_IterateOverSet, 1000000)
530 BENCHMARK_PARAM(BM_IterateSkipList, 1000000)
532 
533 // find with keys in the set
534 BENCHMARK_PARAM(BM_SetContainsFound, 1000)
535 BENCHMARK_PARAM(BM_CSLContainsFound, 1000)
537 BENCHMARK_PARAM(BM_SetContainsFound, 100000)
538 BENCHMARK_PARAM(BM_CSLContainsFound, 100000)
540 BENCHMARK_PARAM(BM_SetContainsFound, 1000000)
541 BENCHMARK_PARAM(BM_CSLContainsFound, 1000000)
543 BENCHMARK_PARAM(BM_SetContainsFound, 10000000)
544 BENCHMARK_PARAM(BM_CSLContainsFound, 10000000)
546 
547 // find with keys not in the set
548 BENCHMARK_PARAM(BM_SetContainsNotFound, 1000)
549 BENCHMARK_PARAM(BM_CSLContainsNotFound, 1000)
551 BENCHMARK_PARAM(BM_SetContainsNotFound, 100000)
552 BENCHMARK_PARAM(BM_CSLContainsNotFound, 100000)
554 BENCHMARK_PARAM(BM_SetContainsNotFound, 1000000)
555 BENCHMARK_PARAM(BM_CSLContainsNotFound, 1000000)
557 
558 BENCHMARK_PARAM(BM_AddSet, 1000)
559 BENCHMARK_PARAM(BM_AddSkipList, 1000)
561 
562 BENCHMARK_PARAM(BM_AddSet, 65536)
563 BENCHMARK_PARAM(BM_AddSkipList, 65536)
565 
566 BENCHMARK_PARAM(BM_AddSet, 1000000)
567 BENCHMARK_PARAM(BM_AddSkipList, 1000000)
569 
570 BENCHMARK_PARAM(BM_SetMerge, 1000)
571 BENCHMARK_PARAM(BM_CSLMergeIntersection, 1000)
572 BENCHMARK_PARAM(BM_CSLMergeLookup, 1000)
574 
575 BENCHMARK_PARAM(BM_SetMerge, 65536)
576 BENCHMARK_PARAM(BM_CSLMergeIntersection, 65536)
577 BENCHMARK_PARAM(BM_CSLMergeLookup, 65536)
579 
580 BENCHMARK_PARAM(BM_SetMerge, 1000000)
581 BENCHMARK_PARAM(BM_CSLMergeIntersection, 1000000)
582 BENCHMARK_PARAM(BM_CSLMergeLookup, 1000000)
584 
585 // multithreaded benchmarking
586 
587 BENCHMARK_PARAM(BM_ContentionStdSet, 1024)
588 BENCHMARK_PARAM(BM_ContentionCSL, 1024)
590 
591 BENCHMARK_PARAM(BM_ContentionStdSet, 65536)
592 BENCHMARK_PARAM(BM_ContentionCSL, 65536)
594 
595 BENCHMARK_PARAM(BM_ContentionStdSet, 1048576)
596 BENCHMARK_PARAM(BM_ContentionCSL, 1048576)
598 
599 } // namespace
600 
601 int main(int argc, char** argv) {
602  google::InitGoogleLogging(argv[0]);
603  gflags::ParseCommandLineFlags(&argc, &argv, true);
604 
605  initData();
606  runBenchmarks();
607  return 0;
608 }
609 
610 #if 0
611 /*
612 Benchmark on Intel(R) Xeon(R) CPU X5650 @2.67GHz
613 
614 ==============================================================================
615 1 thread Benchmark Iters Total t t/iter iter/sec
616 ------------------------------------------------------------------------------
617  +37.0% BM_Accessor 100000 1.958 ms 19.58 ns 48.71 M
618 * BM_AccessorBasicRefcounting 100000 1.429 ms 14.29 ns 66.74 M
619 ------------------------------------------------------------------------------
620  + 603% BM_IterateOverSet/1000 100000 1.589 ms 15.89 ns 60.02 M
621 * BM_IterateSkipList/1000 100000 226 us 2.26 ns 422 M
622 ------------------------------------------------------------------------------
623  + 107% BM_IterateOverSet/976.6k 100000 8.324 ms 83.24 ns 11.46 M
624 * BM_IterateSkipList/976.6k 100000 4.016 ms 40.16 ns 23.75 M
625 ------------------------------------------------------------------------------
626 * BM_SetContainsFound/1000 100000 7.082 ms 70.82 ns 13.47 M
627  +39.9% BM_CSLContainsFound/1000 100000 9.908 ms 99.08 ns 9.625 M
628 ------------------------------------------------------------------------------
629 * BM_SetContainsFound/97.66k 100000 23.8 ms 238 ns 4.006 M
630  +5.97% BM_CSLContainsFound/97.66k 100000 25.23 ms 252.3 ns 3.781 M
631 ------------------------------------------------------------------------------
632  +33.6% BM_SetContainsFound/976.6k 100000 64.3 ms 643 ns 1.483 M
633 * BM_CSLContainsFound/976.6k 100000 48.13 ms 481.3 ns 1.981 M
634 ------------------------------------------------------------------------------
635  +30.3% BM_SetContainsFound/9.537M 100000 115.1 ms 1.151 us 848.6 k
636 * BM_CSLContainsFound/9.537M 100000 88.33 ms 883.3 ns 1.08 M
637 ------------------------------------------------------------------------------
638 * BM_SetContainsNotFound/1000 100000 2.081 ms 20.81 ns 45.83 M
639  +76.2% BM_CSLContainsNotFound/1000 100000 3.667 ms 36.67 ns 26.01 M
640 ------------------------------------------------------------------------------
641 * BM_SetContainsNotFound/97.66k 100000 6.049 ms 60.49 ns 15.77 M
642  +32.7% BM_CSLContainsNotFound/97.66k 100000 8.025 ms 80.25 ns 11.88 M
643 ------------------------------------------------------------------------------
644 * BM_SetContainsNotFound/976.6k 100000 7.464 ms 74.64 ns 12.78 M
645  +12.8% BM_CSLContainsNotFound/976.6k 100000 8.417 ms 84.17 ns 11.33 M
646 ------------------------------------------------------------------------------
647 * BM_AddSet/1000 100000 29.26 ms 292.6 ns 3.259 M
648  +70.0% BM_AddSkipList/1000 100000 49.75 ms 497.5 ns 1.917 M
649 ------------------------------------------------------------------------------
650 * BM_AddSet/64k 100000 38.73 ms 387.3 ns 2.462 M
651  +55.7% BM_AddSkipList/64k 100000 60.3 ms 603 ns 1.581 M
652 ------------------------------------------------------------------------------
653 * BM_AddSet/976.6k 100000 75.71 ms 757.1 ns 1.26 M
654  +33.6% BM_AddSkipList/976.6k 100000 101.2 ms 1.012 us 965.3 k
655 ------------------------------------------------------------------------------
656  + 716% BM_SetMerge/1000 100000 6.872 ms 68.72 ns 13.88 M
657 * BM_CSLMergeIntersection/1000 100000 842 us 8.42 ns 113.3 M
658  + 268% BM_CSLMergeLookup/1000 100000 3.1 ms 31 ns 30.76 M
659 ------------------------------------------------------------------------------
660  +36.3% BM_SetMerge/64k 100000 14.03 ms 140.3 ns 6.798 M
661  +39.4% BM_CSLMergeIntersection/64k 100000 14.35 ms 143.5 ns 6.645 M
662 * BM_CSLMergeLookup/64k 100000 10.29 ms 102.9 ns 9.266 M
663 ------------------------------------------------------------------------------
664  +10.3% BM_SetMerge/976.6k 100000 46.24 ms 462.4 ns 2.062 M
665  +25.1% BM_CSLMergeIntersection/976.6k 100000 52.47 ms 524.7 ns 1.818 M
666 * BM_CSLMergeLookup/976.6k 100000 41.94 ms 419.3 ns 2.274 M
667 ------------------------------------------------------------------------------
668 
669 
670 ==============================================================================
671 Contention benchmark 7/8 find, 3/32 insert, 1/32 erase
672 
673  4 threads Benchmark Iters Total t t/iter iter/sec
674 ------------------------------------------------------------------------------
675  + 269% BM_ContentionStdSet/1k 100000 75.66 ms 756.6 ns 1.26 M
676 * BM_ContentionCSL/1k 100000 20.47 ms 204.7 ns 4.658 M
677 ------------------------------------------------------------------------------
678  + 228% BM_ContentionStdSet/64k 100000 105.6 ms 1.056 us 924.9 k
679 * BM_ContentionCSL/64k 100000 32.18 ms 321.8 ns 2.963 M
680 ------------------------------------------------------------------------------
681  + 224% BM_ContentionStdSet/1M 100000 117.4 ms 1.174 us 832.2 k
682 * BM_ContentionCSL/1M 100000 36.18 ms 361.8 ns 2.636 M
683 ------------------------------------------------------------------------------
684 
685 
686 12 threads Benchmark Iters Total t t/iter iter/sec
687 ------------------------------------------------------------------------------
688  + 697% BM_ContentionStdSet/1k 100000 455.3 ms 4.553 us 214.5 k
689 * BM_ContentionCSL/1k 100000 57.12 ms 571.2 ns 1.67 M
690 ------------------------------------------------------------------------------
691  +1257% BM_ContentionStdSet/64k 100000 654.9 ms 6.549 us 149.1 k
692 * BM_ContentionCSL/64k 100000 48.24 ms 482.4 ns 1.977 M
693 ------------------------------------------------------------------------------
694  +1262% BM_ContentionStdSet/1M 100000 657.3 ms 6.573 us 148.6 k
695 * BM_ContentionCSL/1M 100000 48.25 ms 482.5 ns 1.977 M
696 ------------------------------------------------------------------------------
697 
698 */
699 #endif
void * ptr
*than *hazptr_holder h
Definition: Hazptr.h:116
std::atomic< int64_t > sum(0)
#define BENCHMARK_SUSPEND
Definition: Benchmark.h:576
std::lock_guard< MicroSpinLock > MSLGuard
double val
Definition: String.cpp:273
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
void runBenchmarks()
Definition: Benchmark.cpp:456
uint32_t twang_32from64(uint64_t key) noexcept
Definition: Hash.h:83
std::vector< std::thread::id > threads
char ** argv
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
auto lock(SynchronizedLocker...lockersIn) -> std::tuple< typename SynchronizedLocker::LockedPtr... >
Definition: Synchronized.h:871
#define BENCHMARK(name,...)
Definition: Benchmark.h:365
DEFINE_int32(num_threads, 12,"num concurrent threads to test")
void init() noexcept
Definition: MicroSpinLock.h:72
static const char *const value
Definition: Conv.cpp:50
#define BENCHMARK_PARAM(name, param)
Definition: Benchmark.h:417
static const int kMaxValue
#define FOR_EACH(i, c)
Definition: Foreach.h:143
g_t g(f_t)
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
#define BENCHMARK_DRAW_LINE()
Definition: Benchmark.h:557
static const int kInitHeadHeight
int main(int argc, char **argv)
std::vector< int > values(1'000)