Adds test drivers for concurrent hash maps
authorPeizhao Ou <peizhaoo@uci.edu>
Tue, 6 Feb 2018 22:07:58 +0000 (14:07 -0800)
committerPeizhao Ou <peizhaoo@uci.edu>
Tue, 6 Feb 2018 22:07:58 +0000 (14:07 -0800)
folly/stress-test/stress-sequential-folly-map.cpp [new file with mode: 0644]

diff --git a/folly/stress-test/stress-sequential-folly-map.cpp b/folly/stress-test/stress-sequential-folly-map.cpp
new file mode 100644 (file)
index 0000000..77dcef5
--- /dev/null
@@ -0,0 +1,219 @@
+#include <folly/concurrency/ConcurrentHashMap.h>
+#include <folly/AtomicHashMap.h>
+#include <folly/AtomicUnorderedMap.h>
+
+
+#include <chrono>
+#include <cassert>
+#include <iostream>
+#include <memory>
+
+namespace {
+
+const unsigned s_nInsertPercentage = 10;
+const char* kTestName = "InsDelFind";
+
+const size_t kConcurrentHashMapSize = 10000;
+const size_t kConcurrentHashMapPassCount = 6000;
+const char* kConcurrentHashMapBenchmarkName = "FollyConcurrentHashMap";
+
+const size_t kAtomicHashMapSize = 10000;
+const size_t kAtomicHashMapPassCount = 16000;
+const char* kAtomicHashMapBenchmarkName = "FollyAtomicHashMap";
+
+const size_t kAtomicUnorderedInsertMapSize = 10000;
+const size_t kAtomicUnorderedInsertMapPassCount = 32000;
+const char* kAtomicUnorderedInsertMapBenchmarkName =
+    "FollyAtomicUnorderedInsertMap";
+
+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,
+                                     const char* bench_name) {
+    std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
+    auto start_time = std::chrono::system_clock::now();
+
+    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;
+//                    std::cout << "Found" << i << "\n";
+                }
+            }
+        }
+    }
+    auto finish_time = std::chrono::system_clock::now();
+    auto dur = finish_time - start_time;
+    auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
+
+    if (nFindSuccess != nInsertedNum) {
+        std::cout << "nFindSuccess=" << nFindSuccess << ", nInsertedNum="
+                  << nInsertedNum << std::endl;
+        std::cout << "[       FAILED ] " << kTestName << "." << bench_name
+                  << " (" << milisecs.count() << " ms)" << std::endl;
+        assert(false && "ConcurrentMap ERROR");
+    } else {
+        std::cout << "[       OK ] " << kTestName << "." << bench_name
+                  << " (" << milisecs.count() << " ms)" << std::endl;
+    }
+}
+
+template <typename Map>
+void run_atomic_hashmap(size_t map_size, size_t pass_count, const char* bench_name) {
+    std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
+    auto start_time = std::chrono::system_clock::now();
+
+    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;
+//                    std::cout << "Found" << i << "\n";
+                }
+            }
+        }
+    }
+    auto finish_time = std::chrono::system_clock::now();
+    auto dur = finish_time - start_time;
+    auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
+
+    if (nFindSuccess != nInsertedNum) {
+        std::cout << "nFindSuccess=" << nFindSuccess << ", nInsertedNum="
+                  << nInsertedNum << std::endl;
+        std::cout << "[       FAILED ] " << kTestName << "." << bench_name
+                  << " (" << milisecs.count() << " ms)" << std::endl;
+        assert(false && "ConcurrentMap ERROR");
+    } else {
+        std::cout << "[       OK ] " << kTestName << "." << bench_name
+                  << " (" << milisecs.count() << " ms)" << std::endl;
+    }
+}
+
+template <typename Map>
+void run_concurrent_hashmap(size_t map_size, size_t pass_count,
+                            const char* bench_name) {
+    std::cout << "[ RUN      ] " << kTestName << "." << bench_name << std::endl;
+    auto start_time = std::chrono::system_clock::now();
+
+    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++;
+//              std::cout << "Inserted" << i << "\n";
+            }
+            // Find
+            {
+                if (map_contains(map.get(), i)) {
+                    ++nFindSuccess;
+//                    std::cout << "Found" << i << "\n";
+                }
+            }
+            // Delete
+            if (i % s_nInsertPercentage == 1) {
+                if (map_contains(map.get(), i)) {
+                    map->erase(i);
+//                    std::cout << "Erased" << i << "\n";
+                }
+            }
+        }
+    }
+    auto finish_time = std::chrono::system_clock::now();
+    auto dur = finish_time - start_time;
+    auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
+
+    if (nFindSuccess != nInsertedNum) {
+        std::cout << "nFindSuccess=" << nFindSuccess << ", nInsertedNum="
+                  << nInsertedNum << std::endl;
+        std::cout << "[       FAILED ] " << kTestName << "." << bench_name
+                  << " (" << milisecs.count() << " ms)" << std::endl;
+        assert(false && "ConcurrentMap ERROR");
+    } else {
+        std::cout << "[       OK ] " << kTestName << "." << bench_name
+                  << " (" << milisecs.count() << " ms)" << std::endl;
+    }
+}
+
+int main() {
+  run_concurrent_hashmap<ConcurrentHashMap>(
+          kConcurrentHashMapSize,
+          kConcurrentHashMapPassCount,
+          kConcurrentHashMapBenchmarkName);
+  run_atomic_hashmap<AtomicHashMap>(
+          kAtomicHashMapSize,
+          kAtomicHashMapPassCount,
+          kAtomicHashMapBenchmarkName);
+  run_atomic_unordered_insert_map<AtomicUnorderedInsertMap>(
+          kAtomicUnorderedInsertMapSize,
+          kAtomicUnorderedInsertMapPassCount,
+          kAtomicUnorderedInsertMapBenchmarkName);
+
+  return 0;
+}