1 #include <folly/concurrency/ConcurrentHashMap.h>
2 #include <folly/AtomicHashMap.h>
3 #include <folly/AtomicUnorderedMap.h>
13 const unsigned s_nInsertPercentage = 10;
14 const char* kTestName = "InsDelFind";
16 const size_t kConcurrentHashMapSize = 10000;
17 const size_t kConcurrentHashMapPassCount = 6000;
18 const char* kConcurrentHashMapBenchmarkName = "FollyConcurrentHashMap";
20 const size_t kAtomicHashMapSize = 10000;
21 const size_t kAtomicHashMapPassCount = 16000;
22 const char* kAtomicHashMapBenchmarkName = "FollyAtomicHashMap";
24 const size_t kAtomicUnorderedInsertMapSize = 10000;
25 const size_t kAtomicUnorderedInsertMapPassCount = 32000;
26 const char* kAtomicUnorderedInsertMapBenchmarkName =
27 "FollyAtomicUnorderedInsertMap";
29 typedef folly::ConcurrentHashMap<size_t, size_t> ConcurrentHashMap;
30 typedef folly::AtomicHashMap<size_t, size_t> AtomicHashMap;
31 typedef folly::AtomicUnorderedInsertMap64<size_t, size_t>
32 AtomicUnorderedInsertMap;
35 template <typename Key>
36 bool map_contains(const AtomicUnorderedInsertMap* map, Key key) {
37 return map->find(key) != map->cend();
40 template <typename Key>
41 bool map_contains(const ConcurrentHashMap* map, Key key) {
42 return map->find(key) != map->cend();
45 template <typename Map, typename Key>
46 bool map_contains(const Map* map, Key key) {
47 return map->find(key) != map->end();
50 template <typename Map>
51 void run_atomic_unordered_insert_map(size_t map_size, size_t pass_count,
52 const char* bench_name) {
53 std::cout << "[ RUN ] " << kTestName << "." << bench_name << std::endl;
54 auto start_time = std::chrono::system_clock::now();
56 size_t nInsertedNum = 0;
57 size_t nFindSuccess = 0;
58 std::unique_ptr<Map> map(new Map(map_size));
59 for (size_t count = 0; count < pass_count; count++) {
60 for (size_t i = 0; i < map_size; ++i) {
61 // The number to operate on the map.
62 size_t n = map_size + i;
64 if (i % s_nInsertPercentage == 1) {
65 auto iter = map->find(i);
66 if (iter != map->cend()) {
67 if (iter->second == n) {
68 map->emplace(i, n / 2);
79 if (map_contains(map.get(), i)) {
81 // std::cout << "Found" << i << "\n";
86 auto finish_time = std::chrono::system_clock::now();
87 auto dur = finish_time - start_time;
88 auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
90 if (nFindSuccess != nInsertedNum) {
91 std::cout << "nFindSuccess=" << nFindSuccess << ", nInsertedNum="
92 << nInsertedNum << std::endl;
93 std::cout << "[ FAILED ] " << kTestName << "." << bench_name
94 << " (" << milisecs.count() << " ms)" << std::endl;
95 assert(false && "ConcurrentMap ERROR");
97 std::cout << "[ OK ] " << kTestName << "." << bench_name
98 << " (" << milisecs.count() << " ms)" << std::endl;
102 template <typename Map>
103 void run_atomic_hashmap(size_t map_size, size_t pass_count, const char* bench_name) {
104 std::cout << "[ RUN ] " << kTestName << "." << bench_name << std::endl;
105 auto start_time = std::chrono::system_clock::now();
107 size_t nInsertedNum = 0;
108 size_t nFindSuccess = 0;
109 std::unique_ptr<Map> map(new Map(map_size));
110 for (size_t count = 0; count < pass_count; count++) {
111 for (size_t i = 0; i < map_size; ++i) {
112 // The number to operate on the map.
113 size_t n = map_size + i;
115 if (i % s_nInsertPercentage == 1) {
116 auto iter = map->find(i);
117 if (iter != map->end()) {
118 if (iter->second == n) {
119 iter->second = n / 2;
130 if (map_contains(map.get(), i)) {
132 // std::cout << "Found" << i << "\n";
137 auto finish_time = std::chrono::system_clock::now();
138 auto dur = finish_time - start_time;
139 auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
141 if (nFindSuccess != nInsertedNum) {
142 std::cout << "nFindSuccess=" << nFindSuccess << ", nInsertedNum="
143 << nInsertedNum << std::endl;
144 std::cout << "[ FAILED ] " << kTestName << "." << bench_name
145 << " (" << milisecs.count() << " ms)" << std::endl;
146 assert(false && "ConcurrentMap ERROR");
148 std::cout << "[ OK ] " << kTestName << "." << bench_name
149 << " (" << milisecs.count() << " ms)" << std::endl;
153 template <typename Map>
154 void run_concurrent_hashmap(size_t map_size, size_t pass_count,
155 const char* bench_name) {
156 std::cout << "[ RUN ] " << kTestName << "." << bench_name << std::endl;
157 auto start_time = std::chrono::system_clock::now();
159 size_t nInsertedNum = 0;
160 size_t nFindSuccess = 0;
161 std::unique_ptr<Map> map(new Map(map_size));
162 for (size_t count = 0; count < pass_count; count++) {
163 for (size_t i = 0; i < map_size; ++i) {
164 // The number to operate on the map.
165 size_t n = map_size + i;
167 if (i % s_nInsertPercentage == 1) {
168 auto iter = map->insert({i, n});
170 // std::cout << "Inserted" << i << "\n";
174 if (map_contains(map.get(), i)) {
176 // std::cout << "Found" << i << "\n";
180 if (i % s_nInsertPercentage == 1) {
181 if (map_contains(map.get(), i)) {
183 // std::cout << "Erased" << i << "\n";
188 auto finish_time = std::chrono::system_clock::now();
189 auto dur = finish_time - start_time;
190 auto milisecs = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
192 if (nFindSuccess != nInsertedNum) {
193 std::cout << "nFindSuccess=" << nFindSuccess << ", nInsertedNum="
194 << nInsertedNum << std::endl;
195 std::cout << "[ FAILED ] " << kTestName << "." << bench_name
196 << " (" << milisecs.count() << " ms)" << std::endl;
197 assert(false && "ConcurrentMap ERROR");
199 std::cout << "[ OK ] " << kTestName << "." << bench_name
200 << " (" << milisecs.count() << " ms)" << std::endl;
205 run_concurrent_hashmap<ConcurrentHashMap>(
206 kConcurrentHashMapSize,
207 kConcurrentHashMapPassCount,
208 kConcurrentHashMapBenchmarkName);
209 run_atomic_hashmap<AtomicHashMap>(
211 kAtomicHashMapPassCount,
212 kAtomicHashMapBenchmarkName);
213 run_atomic_unordered_insert_map<AtomicUnorderedInsertMap>(
214 kAtomicUnorderedInsertMapSize,
215 kAtomicUnorderedInsertMapPassCount,
216 kAtomicUnorderedInsertMapBenchmarkName);