From 4ae199e757d6a828bba2f5a4c56ce2b4d4ee57af Mon Sep 17 00:00:00 2001 From: Peizhao Ou Date: Tue, 6 Feb 2018 14:07:58 -0800 Subject: [PATCH] Adds test drivers for concurrent hash maps --- .../stress-sequential-folly-map.cpp | 219 ++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 folly/stress-test/stress-sequential-folly-map.cpp diff --git a/folly/stress-test/stress-sequential-folly-map.cpp b/folly/stress-test/stress-sequential-folly-map.cpp new file mode 100644 index 00000000..77dcef58 --- /dev/null +++ b/folly/stress-test/stress-sequential-folly-map.cpp @@ -0,0 +1,219 @@ +#include +#include +#include + + +#include +#include +#include +#include + +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 ConcurrentHashMap; +typedef folly::AtomicHashMap AtomicHashMap; +typedef folly::AtomicUnorderedInsertMap64 + AtomicUnorderedInsertMap; +} + +template +bool map_contains(const AtomicUnorderedInsertMap* map, Key key) { + return map->find(key) != map->cend(); +} + +template +bool map_contains(const ConcurrentHashMap* map, Key key) { + return map->find(key) != map->cend(); +} + +template +bool map_contains(const Map* map, Key key) { + return map->find(key) != map->end(); +} + +template +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(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(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 +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(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(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 +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(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(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( + kConcurrentHashMapSize, + kConcurrentHashMapPassCount, + kConcurrentHashMapBenchmarkName); + run_atomic_hashmap( + kAtomicHashMapSize, + kAtomicHashMapPassCount, + kAtomicHashMapBenchmarkName); + run_atomic_unordered_insert_map( + kAtomicUnorderedInsertMapSize, + kAtomicUnorderedInsertMapPassCount, + kAtomicUnorderedInsertMapBenchmarkName); + + return 0; +} -- 2.34.1