Uses cmake to build folly test drivers
[folly.git] / folly / stress-test / stress-parallel-folly-map.cpp
diff --git a/folly/stress-test/stress-parallel-folly-map.cpp b/folly/stress-test/stress-parallel-folly-map.cpp
new file mode 100644 (file)
index 0000000..53b9529
--- /dev/null
@@ -0,0 +1,168 @@
+#include <folly/concurrency/ConcurrentHashMap.h>
+#include <folly/AtomicHashMap.h>
+#include <folly/AtomicUnorderedMap.h>
+
+#include <gtest/gtest.h>
+
+#include <memory>
+
+namespace {
+
+const unsigned s_nInsertPercentage = 10;
+
+const size_t kConcurrentHashMapSize = 10000;
+const size_t kConcurrentHashMapPassCount = 36000;
+
+const size_t kAtomicHashMapSize = 10000;
+const size_t kAtomicHashMapPassCount = 250000;
+
+const size_t kAtomicUnorderedInsertMapSize = 10000;
+const size_t kAtomicUnorderedInsertMapPassCount = 500000;
+
+typedef folly::ConcurrentHashMap<size_t, size_t> ConcurrentHashMap;
+typedef folly::AtomicHashMap<size_t, size_t> AtomicHashMap;
+typedef folly::AtomicUnorderedInsertMap64<size_t, size_t>
+    AtomicUnorderedInsertMap;
+}
+
+template <typename Key>
+bool map_contains(const AtomicUnorderedInsertMap* map, Key key) {
+  return map->find(key) != map->cend();
+}
+
+template <typename Key>
+bool map_contains(const ConcurrentHashMap* map, Key key) {
+  return map->find(key) != map->cend();
+}
+
+template <typename Map, typename Key>
+bool map_contains(const Map* map, Key key) {
+  return map->find(key) != map->end();
+}
+
+template <typename Map>
+void run_atomic_unordered_insert_map(size_t map_size, size_t pass_count) {
+    size_t nInsertedNum = 0;
+    size_t nFindSuccess = 0;
+    std::unique_ptr<Map> map(new Map(map_size));
+    for (size_t count = 0; count < pass_count; count++) {
+        for (size_t i = 0; i < map_size; ++i) {
+            // The number to operate on the map.
+            size_t n = map_size + i;
+            // Insert
+            if (i % s_nInsertPercentage == 1) {
+                auto iter = map->find(i);
+                if (iter != map->cend()) {
+                  if (iter->second == n) {
+                    map->emplace(i, n / 2);
+                  } else {
+                    map->emplace(i, n);
+                  }
+                } else {
+                  map->emplace(i, n);
+                }
+                nInsertedNum++;
+            }
+            // Find
+            {
+                if (map_contains(map.get(), i)) {
+                    ++nFindSuccess;
+                }
+            }
+        }
+    }
+    EXPECT_EQ(nFindSuccess, nInsertedNum);
+}
+
+template <typename Map>
+void run_atomic_hashmap(size_t map_size, size_t pass_count) {
+    size_t nInsertedNum = 0;
+    size_t nFindSuccess = 0;
+    std::unique_ptr<Map> map(new Map(map_size));
+    for (size_t count = 0; count < pass_count; count++) {
+        for (size_t i = 0; i < map_size; ++i) {
+            // The number to operate on the map.
+            size_t n = map_size + i;
+            // Insert
+            if (i % s_nInsertPercentage == 1) {
+                auto iter = map->find(i);
+                if (iter != map->end()) {
+                  if (iter->second == n) {
+                    iter->second = n / 2;
+                  } else {
+                    iter->second = n;
+                  }
+                } else {
+                  map->insert({i, n});
+                }
+                nInsertedNum++;
+            }
+            // Find
+            {
+                if (map_contains(map.get(), i)) {
+                    ++nFindSuccess;
+                }
+            }
+        }
+    }
+    EXPECT_EQ(nFindSuccess, nInsertedNum);
+}
+
+template <typename Map>
+void run_concurrent_hashmap(size_t map_size, size_t pass_count) {
+    size_t nInsertedNum = 0;
+    size_t nFindSuccess = 0;
+    std::unique_ptr<Map> map(new Map(map_size));
+    for (size_t count = 0; count < pass_count; count++) {
+        for (size_t i = 0; i < map_size; ++i) {
+            // The number to operate on the map.
+            size_t n = map_size + i;
+            // Insert
+            if (i % s_nInsertPercentage == 1) {
+                  auto iter = map->insert({i, n});
+                  nInsertedNum++;
+            }
+            // Find
+            {
+                if (map_contains(map.get(), i)) {
+                    ++nFindSuccess;
+                }
+            }
+            // Delete
+            if (i % s_nInsertPercentage == 1) {
+                if (map_contains(map.get(), i)) {
+                    map->erase(i);
+                }
+            }
+        }
+    }
+    EXPECT_EQ(nFindSuccess, nInsertedNum);
+}
+
+class FollyMapInsDelFindTest: public ::testing::Test {
+};
+
+TEST_F(FollyMapInsDelFindTest, FollyConcurrentHashMap) {
+  run_concurrent_hashmap<ConcurrentHashMap>(
+          kConcurrentHashMapSize,
+          kConcurrentHashMapPassCount);
+}
+
+TEST_F(FollyMapInsDelFindTest, FollyAtomicHashMap) {
+  run_atomic_hashmap<AtomicHashMap>(
+          kAtomicHashMapSize,
+          kAtomicHashMapPassCount);
+}
+
+TEST_F(FollyMapInsDelFindTest, FollyAtomicUnorderedInsertMap) {
+  run_atomic_unordered_insert_map<AtomicUnorderedInsertMap>(
+          kAtomicUnorderedInsertMapSize,
+          kAtomicUnorderedInsertMapPassCount);
+}
+
+int main(int argc, char** argv) {
+  // Init Google test
+  ::testing::InitGoogleTest(&argc, argv);
+  int result = RUN_ALL_TESTS();
+  return result;
+}