proxygen
AHMIntStressTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2013-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <memory>
18 #include <mutex>
19 #include <thread>
20 
21 #include <folly/AtomicHashMap.h>
22 #include <folly/Memory.h>
23 #include <folly/ScopeGuard.h>
25 
26 namespace {
27 
28 struct MyObject {
29  explicit MyObject(int i_) : i(i_) {}
30  int i;
31 };
32 
34 typedef std::lock_guard<std::mutex> Guard;
35 
36 std::unique_ptr<MyMap> newMap() {
37  return std::make_unique<MyMap>(100);
38 }
39 
40 struct MyObjectDirectory {
41  MyObjectDirectory() : cur_(newMap()), prev_(newMap()) {}
42 
43  std::shared_ptr<MyObject> get(int key) {
44  auto val = tryGet(key);
45  if (val) {
46  return val;
47  }
48 
49  std::shared_ptr<MyMap> cur;
50  {
51  Guard g(lock_);
52  cur = cur_;
53  }
54 
55  auto ret = cur->insert(key, std::make_shared<MyObject>(key));
56  return ret.first->second;
57  }
58 
59  std::shared_ptr<MyObject> tryGet(int key) {
60  std::shared_ptr<MyMap> cur;
61  std::shared_ptr<MyMap> prev;
62  {
63  Guard g(lock_);
64  cur = cur_;
65  prev = prev_;
66  }
67 
68  auto it = cur->find(key);
69  if (it != cur->end()) {
70  return it->second;
71  }
72 
73  it = prev->find(key);
74  if (it != prev->end()) {
75  auto ret = cur->insert(key, it->second);
76  return ret.first->second;
77  }
78 
79  return nullptr;
80  }
81 
82  void archive() {
83  std::shared_ptr<MyMap> cur(newMap());
84 
85  Guard g(lock_);
86  prev_ = cur_;
87  cur_ = cur;
88  }
89 
90  std::mutex lock_;
91  std::shared_ptr<MyMap> cur_;
92  std::shared_ptr<MyMap> prev_;
93 };
94 
95 } // namespace
96 
98 
99 /*
100  * This test case stresses ThreadLocal allocation/deallocation heavily
101  * via ThreadCachedInt and AtomicHashMap, and a bunch of other
102  * mallocing.
103  */
104 TEST(AHMIntStressTest, Test) {
105  auto const objs = new MyObjectDirectory();
106  SCOPE_EXIT {
107  delete objs;
108  };
109 
110  std::vector<std::thread> threads;
111  for (int threadId = 0; threadId < 64; ++threadId) {
112  threads.emplace_back([objs] {
113  for (int recycles = 0; recycles < 500; ++recycles) {
114  for (int i = 0; i < 10; i++) {
115  auto val = objs->get(i);
116  }
117 
118  objs->archive();
119  }
120  });
121  }
122 
123  for (auto& t : threads) {
124  t.join();
125  }
126 }
double val
Definition: String.cpp:273
#define SCOPE_EXIT
Definition: ScopeGuard.h:274
TEST(AHMIntStressTest, Test)
std::vector< std::thread::id > threads
std::mutex mutex
g_t g(f_t)