proxygen
AtomicUnorderedMapTest.cpp File Reference
#include <folly/AtomicUnorderedMap.h>
#include <memory>
#include <thread>
#include <unordered_map>
#include <folly/Benchmark.h>
#include <folly/portability/GFlags.h>
#include <folly/portability/GTest.h>
#include <folly/portability/Semaphore.h>
#include <folly/test/DeterministicSchedule.h>

Go to the source code of this file.

Classes

struct  non_atomic< T >
 
struct  PairHash
 

Typedefs

template<typename Key , typename Value , typename IndexType , template< typename > class Atom = std::atomic, typename Allocator = std::allocator<char>>
using UIM = AtomicUnorderedInsertMap< Key, Value, std::hash< Key >, std::equal_to< Key >,(boost::has_trivial_destructor< Key >::value &&boost::has_trivial_destructor< Value >::value), Atom, IndexType, Allocator >
 
using IndexTypesToTest = ::testing::Types< uint16_t, uint32_t, uint64_t >
 

Functions

 TYPED_TEST_CASE (AtomicUnorderedInsertMapTest, IndexTypesToTest)
 
 TYPED_TEST (AtomicUnorderedInsertMapTest, basic)
 
 TEST (AtomicUnorderedInsertMap, load_factor)
 
 TEST (AtomicUnorderedInsertMap, capacity_exceeded)
 
 TYPED_TEST (AtomicUnorderedInsertMapTest, value_mutation)
 
 TEST (UnorderedInsertMap, value_mutation)
 
 TEST (AtomicUnorderedInsertMap, DISABLED_mega_map)
 
 BENCHMARK (lookup_int_int_hit, iters)
 
void contendedRW (size_t itersPerThread, size_t capacity, size_t numThreads, size_t readsPerWrite)
 
 BENCHMARK_DRAW_LINE ()
 
 BENCHMARK (std_map)
 
 BENCHMARK (atomic_fast_map)
 
 BENCHMARK (fast_map)
 
 BENCHMARK (atomic_fast_map_64)
 
 BENCHMARK (fast_map_64)
 
int main (int argc, char **argv)
 

Typedef Documentation

using IndexTypesToTest = ::testing::Types<uint16_t, uint32_t, uint64_t>

Definition at line 125 of file AtomicUnorderedMapTest.cpp.

template<typename Key , typename Value , typename IndexType , template< typename > class Atom = std::atomic, typename Allocator = std::allocator<char>>
using UIM = AtomicUnorderedInsertMap< Key, Value, std::hash<Key>, std::equal_to<Key>, (boost::has_trivial_destructor<Key>::value && boost::has_trivial_destructor<Value>::value), Atom, IndexType, Allocator>

Definition at line 116 of file AtomicUnorderedMapTest.cpp.

Function Documentation

BENCHMARK ( lookup_int_int_hit  ,
iters   
)

Definition at line 217 of file AtomicUnorderedMapTest.cpp.

References BENCHMARK_SUSPEND, EXPECT_EQ, EXPECT_TRUE, i, k, and ptr.

217  {
218  std::unique_ptr<AtomicUnorderedInsertMap<int, size_t>> ptr = {};
219 
220  size_t capacity = 100000;
221 
223  ptr = std::make_unique<AtomicUnorderedInsertMap<int, size_t>>(capacity);
224  for (size_t i = 0; i < capacity; ++i) {
225  auto k = 3 * ((5641 * i) % capacity);
226  ptr->emplace(k, k + 1);
227  EXPECT_EQ(ptr->find(k)->second, k + 1);
228  }
229  }
230 
231  for (size_t i = 0; i < iters; ++i) {
232  size_t k = 3 * (((i * 7919) ^ (i * 4001)) % capacity);
233  auto iter = ptr->find(k);
234  if (iter == ptr->cend() || iter->second != k + 1) {
235  auto jter = ptr->find(k);
236  EXPECT_TRUE(iter == jter);
237  }
238  EXPECT_EQ(iter->second, k + 1);
239  }
240 
242  ptr.reset(nullptr);
243  }
244 }
void * ptr
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define BENCHMARK_SUSPEND
Definition: Benchmark.h:576
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
KeyT k
BENCHMARK ( std_map  )

Definition at line 353 of file AtomicUnorderedMapTest.cpp.

References a, folly::doNotOptimizeAway(), i, and m.

353  {
354  std::unordered_map<long, long> m;
355  m.reserve(10000);
356  for (int i = 0; i < 10000; ++i) {
357  m.emplace(i, i);
358  }
359 
360  for (int i = 0; i < 10000; ++i) {
361  auto a = m.find(i);
363  }
364 }
static map< string, int > m
char a
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258
BENCHMARK ( atomic_fast_map  )

Definition at line 366 of file AtomicUnorderedMapTest.cpp.

References a, folly::doNotOptimizeAway(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::emplace(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::find(), i, and m.

366  {
368  for (int i = 0; i < 10000; ++i) {
369  m.emplace(i, i);
370  }
371 
372  for (int i = 0; i < 10000; ++i) {
373  auto a = m.find(i);
375  }
376 }
static map< string, int > m
char a
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258
BENCHMARK ( fast_map  )

Definition at line 378 of file AtomicUnorderedMapTest.cpp.

References a, folly::doNotOptimizeAway(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::emplace(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::find(), i, and m.

378  {
380  for (int i = 0; i < 10000; ++i) {
381  m.emplace(i, i);
382  }
383 
384  for (int i = 0; i < 10000; ++i) {
385  auto a = m.find(i);
387  }
388 }
static map< string, int > m
char a
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258
BENCHMARK ( atomic_fast_map_64  )

Definition at line 390 of file AtomicUnorderedMapTest.cpp.

References a, folly::doNotOptimizeAway(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::emplace(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::find(), i, and m.

390  {
392  for (int i = 0; i < 10000; ++i) {
393  m.emplace(i, i);
394  }
395 
396  for (int i = 0; i < 10000; ++i) {
397  auto a = m.find(i);
399  }
400 }
static map< string, int > m
char a
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258
BENCHMARK ( fast_map_64  )

Definition at line 402 of file AtomicUnorderedMapTest.cpp.

References a, folly::doNotOptimizeAway(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::emplace(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::find(), i, and m.

402  {
404  for (int i = 0; i < 10000; ++i) {
405  m.emplace(i, i);
406  }
407 
408  for (int i = 0; i < 10000; ++i) {
409  auto a = m.find(i);
411  }
412 }
static map< string, int > m
char a
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258
BENCHMARK_DRAW_LINE ( )
void contendedRW ( size_t  itersPerThread,
size_t  capacity,
size_t  numThreads,
size_t  readsPerWrite 
)

Definition at line 252 of file AtomicUnorderedMapTest.cpp.

References folly::BENCHMARK_DRAW_LINE(), BENCHMARK_NAMED_PARAM, BENCHMARK_SUSPEND, EXPECT_TRUE, folly::INFO, testing::Key(), ptr, folly::Random::rand32(), threads, and folly::fibers::yield().

256  {
257  typedef std::pair<uint64_t, uint64_t> Key;
259 
260  std::unique_ptr<Map> ptr = {};
261  std::atomic<bool> go{false};
262  std::vector<std::thread> threads;
263 
265  ptr = std::make_unique<Map>(capacity);
266  while (threads.size() < numThreads) {
267  threads.emplace_back([&]() {
268  while (!go) {
270  }
271 
272  size_t reads = 0;
273  size_t writes = 0;
274  while (reads + writes < itersPerThread) {
275  auto r = Random::rand32();
276  Key key(reads + writes, r);
277  if (reads < writes * readsPerWrite ||
278  writes >= capacity / numThreads) {
279  // read needed
280  ++reads;
281  auto iter = ptr->find(key);
282  EXPECT_TRUE(
283  iter == ptr->cend() ||
284  iter->second.data.load(std::memory_order_acquire) >= key.first);
285  } else {
286  ++writes;
287  try {
288  auto pr = ptr->emplace(key, key.first);
289  if (!pr.second) {
290  pr.first->second.data++;
291  }
292  } catch (std::bad_alloc&) {
293  LOG(INFO) << "bad alloc";
294  }
295  }
296  }
297  });
298  }
299  }
300 
301  go = true;
302 
303  for (auto& thr : threads) {
304  thr.join();
305  }
306 
308  ptr.reset(nullptr);
309  }
310 }
void * ptr
#define BENCHMARK_SUSPEND
Definition: Benchmark.h:576
internal::KeyMatcher< M > Key(M inner_matcher)
std::unordered_map< int64_t, VecT > Map
std::vector< std::thread::id > threads
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
int main ( int  argc,
char **  argv 
)

Definition at line 414 of file AtomicUnorderedMapTest.cpp.

References testing::InitGoogleTest(), RUN_ALL_TESTS(), and folly::runBenchmarksOnFlag().

414  {
416  gflags::ParseCommandLineFlags(&argc, &argv, true);
417  int rv = RUN_ALL_TESTS();
419  return rv;
420 }
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_
Definition: gtest.h:2232
char ** argv
bool runBenchmarksOnFlag()
Definition: Benchmark.h:48
GTEST_API_ void InitGoogleTest(int *argc, char **argv)
Definition: gtest.cc:5370
TEST ( AtomicUnorderedInsertMap  ,
load_factor   
)

Definition at line 156 of file AtomicUnorderedMapTest.cpp.

References folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::emplace(), f, i, and m.

156  {
158 
159  // we should be able to put in much more than 5000 things because of
160  // our load factor request
161  for (int i = 0; i < 10000; ++i) {
162  m.emplace(i, true);
163  }
164 }
auto f
static map< string, int > m
TEST ( AtomicUnorderedInsertMap  ,
capacity_exceeded   
)

Definition at line 166 of file AtomicUnorderedMapTest.cpp.

References folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::emplace(), EXPECT_THROW, f, i, and m.

166  {
168 
169  EXPECT_THROW(
170  {
171  for (int i = 0; i < 6000; ++i) {
172  m.emplace(i, false);
173  }
174  },
175  std::bad_alloc);
176 }
auto f
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
static map< string, int > m
TEST ( UnorderedInsertMap  ,
value_mutation   
)
TEST ( AtomicUnorderedInsertMap  ,
DISABLED_mega_map   
)

Definition at line 201 of file AtomicUnorderedMapTest.cpp.

References folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::cend(), folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::emplace(), EXPECT_EQ, EXPECT_TRUE, folly::AtomicUnorderedInsertMap< Key, Value, Hash, KeyEqual, SkipKeyValueDeletion, Atom, IndexType, Allocator >::find(), and i.

201  {
202  size_t capacity = 2000000000;
204  for (size_t i = 0; i < capacity * 2; i += 2) {
205  big.emplace(i, i * 10);
206  }
207  for (size_t i = 0; i < capacity * 3; i += capacity / 1000 + 1) {
208  auto iter = big.find(i);
209  if ((i & 1) == 0 && i < capacity * 2) {
210  EXPECT_EQ(iter->second, i * 10);
211  } else {
212  EXPECT_TRUE(iter == big.cend());
213  }
214  }
215 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TYPED_TEST ( AtomicUnorderedInsertMapTest  ,
basic   
)

Definition at line 128 of file AtomicUnorderedMapTest.cpp.

References a, b, EXPECT_EQ, EXPECT_TRUE, m, and string.

128  {
130  std::string,
131  TypeParam,
132  std::atomic,
134  m(100);
135 
136  m.emplace("abc", "ABC");
137  EXPECT_TRUE(m.find("abc") != m.cend());
138  EXPECT_EQ(m.find("abc")->first, "abc");
139  EXPECT_EQ(m.find("abc")->second, "ABC");
140  EXPECT_TRUE(m.find("def") == m.cend());
141  auto iter = m.cbegin();
142  EXPECT_TRUE(iter != m.cend());
143  EXPECT_TRUE(iter == m.find("abc"));
144  auto a = iter;
145  EXPECT_TRUE(a == iter);
146  auto b = iter;
147  ++iter;
148  EXPECT_TRUE(iter == m.cend());
149  EXPECT_TRUE(a == b);
150  EXPECT_TRUE(a != iter);
151  a++;
152  EXPECT_TRUE(a == iter);
153  EXPECT_TRUE(a != b);
154 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static map< string, int > m
char a
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
const char * string
Definition: Conv.cpp:212
TYPED_TEST ( AtomicUnorderedInsertMapTest  ,
value_mutation   
)
TYPED_TEST_CASE ( AtomicUnorderedInsertMapTest  ,
IndexTypesToTest   
)