proxygen
ArenaTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2012-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 <folly/memory/Arena.h>
18 #include <folly/Memory.h>
20 
21 #include <set>
22 #include <vector>
23 
24 #include <glog/logging.h>
25 
26 using namespace folly;
27 
29 
30 TEST(Arena, SizeSanity) {
31  std::set<size_t*> allocatedItems;
32 
33  static const size_t requestedBlockSize = 64;
34  SysArena arena(requestedBlockSize);
35  size_t minimum_size = sizeof(SysArena), maximum_size = minimum_size;
36  EXPECT_EQ(arena.totalSize(), minimum_size);
37 
38  // Insert a single small element to get a new block
39  size_t* ptr = static_cast<size_t*>(arena.allocate(sizeof(long)));
40  allocatedItems.insert(ptr);
41  minimum_size += requestedBlockSize;
42  maximum_size += goodMallocSize(requestedBlockSize + SysArena::kBlockOverhead);
43  EXPECT_TRUE(arena.totalSize() >= minimum_size);
44  EXPECT_TRUE(arena.totalSize() <= maximum_size);
45  VLOG(4) << minimum_size << " < " << arena.totalSize() << " < "
46  << maximum_size;
47 
48  // Insert a larger element, size should be the same
49  ptr = static_cast<size_t*>(arena.allocate(requestedBlockSize / 2));
50  allocatedItems.insert(ptr);
51  EXPECT_TRUE(arena.totalSize() >= minimum_size);
52  EXPECT_TRUE(arena.totalSize() <= maximum_size);
53  VLOG(4) << minimum_size << " < " << arena.totalSize() << " < "
54  << maximum_size;
55 
56  // Insert 10 full block sizes to get 10 new blocks
57  for (int i = 0; i < 10; i++) {
58  ptr = static_cast<size_t*>(arena.allocate(requestedBlockSize));
59  allocatedItems.insert(ptr);
60  }
61  minimum_size += 10 * requestedBlockSize;
62  maximum_size +=
63  10 * goodMallocSize(requestedBlockSize + SysArena::kBlockOverhead);
64  EXPECT_TRUE(arena.totalSize() >= minimum_size);
65  EXPECT_TRUE(arena.totalSize() <= maximum_size);
66  VLOG(4) << minimum_size << " < " << arena.totalSize() << " < "
67  << maximum_size;
68 
69  // Insert something huge
70  ptr = static_cast<size_t*>(arena.allocate(10 * requestedBlockSize));
71  allocatedItems.insert(ptr);
72  minimum_size += 10 * requestedBlockSize;
73  maximum_size +=
74  goodMallocSize(10 * requestedBlockSize + SysArena::kBlockOverhead);
75  EXPECT_TRUE(arena.totalSize() >= minimum_size);
76  EXPECT_TRUE(arena.totalSize() <= maximum_size);
77  VLOG(4) << minimum_size << " < " << arena.totalSize() << " < "
78  << maximum_size;
79 
80  // Nuke 'em all
81  for (const auto& item : allocatedItems) {
82  arena.deallocate(item, 0 /* unused */);
83  }
84  // The total size should be the same
85  EXPECT_TRUE(arena.totalSize() >= minimum_size);
86  EXPECT_TRUE(arena.totalSize() <= maximum_size);
87  VLOG(4) << minimum_size << " < " << arena.totalSize() << " < "
88  << maximum_size;
89 }
90 
91 TEST(Arena, BytesUsedSanity) {
92  static const size_t smallChunkSize = 1024;
93  static const size_t blockSize = goodMallocSize(16 * smallChunkSize);
94  const size_t bigChunkSize = blockSize - 4 * smallChunkSize;
95 
96  size_t bytesUsed = 0;
97 
98  SysArena arena(blockSize);
99  EXPECT_EQ(arena.bytesUsed(), bytesUsed);
100 
101  // Insert 2 small chunks
102  arena.allocate(smallChunkSize);
103  arena.allocate(smallChunkSize);
104  bytesUsed += 2 * smallChunkSize;
105  EXPECT_EQ(arena.bytesUsed(), bytesUsed);
106  EXPECT_TRUE(arena.totalSize() >= blockSize);
107  EXPECT_TRUE(arena.totalSize() <= 2 * blockSize);
108 
109  // Insert big chunk, should still fit in one block
110  arena.allocate(bigChunkSize);
111  bytesUsed += bigChunkSize;
112  EXPECT_EQ(arena.bytesUsed(), bytesUsed);
113  EXPECT_TRUE(arena.totalSize() >= blockSize);
114  EXPECT_TRUE(arena.totalSize() <= 2 * blockSize);
115 
116  // Insert big chunk once more, should trigger new block allocation
117  arena.allocate(bigChunkSize);
118  bytesUsed += bigChunkSize;
119  EXPECT_EQ(arena.bytesUsed(), bytesUsed);
120  EXPECT_TRUE(arena.totalSize() >= 2 * blockSize);
121  EXPECT_TRUE(arena.totalSize() <= 3 * blockSize);
122 
123  // Test that bytesUsed() accounts for alignment
124  static const size_t tinyChunkSize = 7;
125  arena.allocate(tinyChunkSize);
126  EXPECT_TRUE(arena.bytesUsed() >= bytesUsed + tinyChunkSize);
127  size_t delta = arena.bytesUsed() - bytesUsed;
128  EXPECT_EQ(delta & (delta - 1), 0);
129 }
130 
131 TEST(Arena, Vector) {
132  static const size_t requestedBlockSize = 64;
133  SysArena arena(requestedBlockSize);
134 
135  EXPECT_EQ(arena.totalSize(), sizeof(SysArena));
136 
137  std::vector<size_t, SysArenaAllocator<size_t>> vec{
138  {}, SysArenaAllocator<size_t>(arena)};
139 
140  for (size_t i = 0; i < 1000; i++) {
141  vec.push_back(i);
142  }
143 
144  for (size_t i = 0; i < 1000; i++) {
145  EXPECT_EQ(i, vec[i]);
146  }
147 }
148 
149 TEST(Arena, SizeLimit) {
150  static const size_t requestedBlockSize = sizeof(size_t);
151  static const size_t maxSize = 10 * requestedBlockSize;
152 
153  SysArena arena(requestedBlockSize, maxSize);
154 
155  void* a = arena.allocate(sizeof(size_t));
156  EXPECT_TRUE(a != nullptr);
157  EXPECT_THROW(arena.allocate(maxSize + 1), std::bad_alloc);
158 }
159 
160 int main(int argc, char* argv[]) {
161  testing::InitGoogleTest(&argc, argv);
162  gflags::ParseCommandLineFlags(&argc, &argv, true);
163  auto ret = RUN_ALL_TESTS();
164  return ret;
165 }
void * ptr
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_
Definition: gtest.h:2232
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
size_t bytesUsed() const
Definition: Arena.h:117
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
static constexpr size_t kBlockOverhead
Definition: Arena.h:156
char ** argv
char a
Definition: Traits.h:588
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
size_t totalSize() const
Definition: Arena.h:109
GTEST_API_ void InitGoogleTest(int *argc, char **argv)
Definition: gtest.cc:5370
void deallocate(void *, size_t=0)
Definition: Arena.h:101
void * allocate(size_t size)
Definition: Arena.h:82
TEST(SequencedExecutor, CPUThreadPoolExecutor)
int main(int argc, char *argv[])
Definition: ArenaTest.cpp:160
size_t goodMallocSize(size_t minSize) noexcept
Definition: Malloc.h:201