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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/wtf/FlatTable.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/wtf/SetPerfTest.cpp
diff --git a/third_party/WebKit/Source/wtf/SetPerfTest.cpp b/third_party/WebKit/Source/wtf/SetPerfTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..466851960b53e172c7d266f3019ed8bc56019952
--- /dev/null
+++ b/third_party/WebKit/Source/wtf/SetPerfTest.cpp
@@ -0,0 +1,289 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <array>
+#include <set>
+#include <unordered_set>
+
+#include "base/bind.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "wtf/FlatSet.h"
+#include "wtf/HashSet.h"
+
+using testing::Values;
+
+template <>
+inline std::string testing::internal::GetTypeName<std::set<int>>() {
+ return "std::set";
+}
+
+template <>
+inline std::string testing::internal::GetTypeName<std::unordered_set<int>>() {
+ return "std::unordered_set";
+}
+
+template <>
+inline std::string testing::internal::GetTypeName<WTF::FlatSet<int>>() {
+ return "WTF::FlatSet";
+}
+
+template <>
+inline std::string testing::internal::GetTypeName<WTF::HashSet<int>>() {
+ return "WTF::HashSet";
+}
+
+using AssociativeSetTypes = testing::Types<std::set<int>, WTF::FlatSet<int>>;
+using SetTypes = testing::Types<std::set<int>,
+ std::unordered_set<int>,
+ WTF::FlatSet<int>,
+ WTF::HashSet<int>>;
+
+namespace WTF {
+
+class Benchmark : public testing::Test {
+ public:
+ Benchmark() {}
+ virtual ~Benchmark() {}
+
+ enum {
+ kBestOfNRuns = 10,
+ kNumPermutedInts = 1 << 15,
+ };
+
+ static void SetUpTestCase() {
+ for (size_t i = 0; i < permuted_ints_.size(); i++)
+ permuted_ints_[i] = i + 1; // WTF::HashSet doesn't like adding 0.
+
+ // Apply a pseudo random permutation.
+ int32_t num = 1234;
+ for (size_t i = 0; i < permuted_ints_.size(); i++) {
+ num = static_cast<int32_t>((num * 16807) % 2147483647L);
+ std::swap(permuted_ints_[i], permuted_ints_[num % permuted_ints_.size()]);
+ }
+ }
+
+ void RunBenchmarkSet(base::Callback<void(size_t)> init,
+ base::Callback<void(size_t)> run) {
+ for (size_t set_size : set_sizes_) {
+ double best_time = 0;
+ for (size_t i = 0; i < kBestOfNRuns; i++) {
+ double time = RunBenchmark(init, run, set_size);
+ if (i == 0) {
+ best_time = time;
+ } else if (time < best_time) {
+ best_time = time;
+ }
+ }
+ std::cout << "Set size " << set_size << " runtime (us) " << best_time
+ << std::endl;
+ }
+ }
+
+ static std::array<int, kNumPermutedInts> permuted_ints_;
+
+ private:
+ double RunBenchmark(base::Callback<void(size_t)> init,
+ base::Callback<void(size_t)> run,
+ size_t set_size) {
+ init.Run(set_size);
+ base::ThreadTicks start = base::ThreadTicks::Now();
+ base::ThreadTicks now;
+ unsigned long long num_iterations = 0;
+ do {
+ run.Run(set_size);
+ now = base::ThreadTicks::Now();
+ num_iterations++;
+ } while (now - start < base::TimeDelta::FromMilliseconds(100));
+ return (now - start).InMicroseconds() / static_cast<double>(num_iterations);
+ }
+
+ std::vector<size_t> set_sizes_ = {1, 2, 4, 8, 16, 32,
+ 64, 128, 256, 512, 1024, 2048,
+ 4096, 8192, 16384, 32768};
+};
+
+std::array<int, Benchmark::kNumPermutedInts> Benchmark::permuted_ints_;
+
+template <typename SetType>
+class SetBenchmark : public Benchmark {
+ public:
+ SetType set_;
+ size_t index_ = 0;
+ size_t run_ = 0;
+
+ void setClear() { set_.clear(); }
+
+ void setInsertUnique(int i) { setInsert(i); }
+
+ void setInsert(int i) { set_.insert(i); }
+
+ void setErase(int i) { set_.erase(i); }
+
+ void setEraseFront() { set_.erase(set_.begin()); }
+
+ void setEraseBack() { set_.erase(std::prev(set_.end())); }
+};
+
+template <>
+void SetBenchmark<FlatSet<int>>::setInsertUnique(int i) {
+ set_.insertUnique(i);
+}
+
+template <>
+void SetBenchmark<FlatSet<int>>::setEraseBack() {
+ set_.erase(set_.rbegin());
+}
+
+template <>
+void SetBenchmark<HashSet<int>>::setInsert(int i) {
+ set_.add(i);
+}
+
+template <>
+void SetBenchmark<HashSet<int>>::setErase(int i) {
+ set_.remove(i);
+}
+
+TYPED_TEST_CASE(SetBenchmark, SetTypes);
+
+TYPED_TEST(SetBenchmark, InsertAndErasePseudoRandom) {
+ Benchmark::RunBenchmarkSet(
+ base::Bind([](SetBenchmark<TypeParam>* fixture,
+ size_t set_size) { fixture->setClear(); },
+ base::Unretained(this)),
+ base::Bind(
+ [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
+ const auto& permutation = Benchmark::permuted_ints_;
+ size_t& index = fixture->index_;
+
+ for (size_t i = 0; i < set_size; i++) {
+ fixture->setInsert(permutation[index++ % permutation.size()]);
+ }
+ for (size_t i = 0; i < set_size; i++) {
+ fixture->setErase(permutation[index++ % permutation.size()]);
+ }
+ },
+ base::Unretained(this)));
+}
+
+TYPED_TEST(SetBenchmark, InsertAndEraseOutsideIn) {
+ Benchmark::RunBenchmarkSet(
+ base::Bind([](SetBenchmark<TypeParam>* fixture,
+ size_t set_size) { fixture->set_.clear(); },
+ base::Unretained(this)),
+ base::Bind(
+ [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
+ for (size_t i = 1; i < set_size; i++) {
+ fixture->setInsertUnique(set_size - i);
+ fixture->setInsertUnique(set_size + i);
+ }
+ for (size_t i = set_size - 1; i > 0; i--) {
+ fixture->setErase(set_size - i);
+ fixture->setErase(set_size + i);
+ }
+ },
+ base::Unretained(this)));
+}
+
+TYPED_TEST(SetBenchmark, InsertAndEraseInsideOut) {
+ Benchmark::RunBenchmarkSet(
+ base::Bind([](SetBenchmark<TypeParam>* fixture,
+ size_t set_size) { fixture->set_.clear(); },
+ base::Unretained(this)),
+ base::Bind(
+ [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
+ for (size_t i = 1; i < set_size; i++) {
+ fixture->setInsertUnique(i);
+ fixture->setInsertUnique(set_size + set_size - i);
+ }
+ for (size_t i = set_size - 1; i > 0; i--) {
+ fixture->setErase(i);
+ fixture->setErase(set_size + set_size - i);
+ }
+ },
+ base::Unretained(this)));
+}
+
+TYPED_TEST(SetBenchmark, FixedSizeFind) {
+ size_t num = 0;
+ Benchmark::RunBenchmarkSet(
+ base::Bind(
+ [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
+ const auto& permutation = Benchmark::permuted_ints_;
+
+ fixture->setClear();
+ for (size_t i = 0; i < set_size; i++)
+ fixture->setInsert(permutation[i % permutation.size()]);
+ },
+ base::Unretained(this)),
+ base::Bind(
+ [](SetBenchmark<TypeParam>* fixture, size_t* num, size_t set_size) {
+ const auto& permutation = Benchmark::permuted_ints_;
+
+ for (size_t i = 0; i < set_size; i++) {
+ if (fixture->set_.find(permutation[i % permutation.size()]) !=
+ fixture->set_.end()) {
+ (*num)++; // Prevent the compiler from optimizing stuff away.
+ }
+ }
+ },
+ base::Unretained(this), base::Unretained(&num)));
+}
+
+template <typename SetType>
+class AssociativeSetBenchmark : public SetBenchmark<SetType> {};
+
+TYPED_TEST_CASE(AssociativeSetBenchmark, AssociativeSetTypes);
+
+TYPED_TEST(AssociativeSetBenchmark, FixedSizeEraseAndInsert) {
+ Benchmark::RunBenchmarkSet(
+ base::Bind(
+ [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
+ const auto& permutation = Benchmark::permuted_ints_;
+ size_t& index = fixture->index_;
+
+ fixture->setClear();
+ for (index = 0; index < set_size; index++) {
+ fixture->setInsert(permutation[index % permutation.size()]);
+ }
+ },
+ base::Unretained(this)),
+ base::Bind(
+ [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
+ const auto& permutation = Benchmark::permuted_ints_;
+ size_t& index = fixture->index_;
+ size_t& run = fixture->run_; // Necessary to ensure uniqueness.
+
+ for (size_t i = 0; i < 10000; i++) {
+ fixture->setEraseFront();
+ fixture->setInsertUnique(
+ run + permutation[index++ % permutation.size()]);
+ }
+
+ run += permutation.size();
+ },
+ base::Unretained(this)));
+}
+
+TYPED_TEST(AssociativeSetBenchmark, InsertAndEraseOutsideIn) {
+ Benchmark::RunBenchmarkSet(
+ base::Bind([](SetBenchmark<TypeParam>* fixture,
+ size_t set_size) { fixture->set_.clear(); },
+ base::Unretained(this)),
+ base::Bind(
+ [](SetBenchmark<TypeParam>* fixture, size_t set_size) {
+ for (size_t i = 1; i < set_size; i++) {
+ fixture->setInsertUnique(set_size - i);
+ fixture->setInsertUnique(set_size + i);
+ }
+ for (size_t i = set_size - 1; i > 0; i--) {
+ fixture->setEraseFront();
+ fixture->setEraseBack();
+ }
+ },
+ base::Unretained(this)));
+ EXPECT_TRUE(this->set_.empty());
+}
+
+} // namespace WTF
« 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