Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
free-pool-test.cc
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string>
16 #include <gtest/gtest.h>
17 
18 #include "runtime/free-pool.h"
19 #include "runtime/mem-pool.h"
20 #include "runtime/mem-tracker.h"
21 
22 #include "common/names.h"
23 
24 namespace impala {
25 
26 TEST(FreePoolTest, Basic) {
28  MemPool mem_pool(&tracker);
29  FreePool pool(&mem_pool);
30 
31  // Start off with some corner cases.
32  uint8_t* p1 = pool.Allocate(0);
33  DCHECK(p1 != NULL);
34  pool.Free(p1);
35  pool.Free(NULL);
36 
37  EXPECT_EQ(mem_pool.total_allocated_bytes(), 0);
38  p1 = pool.Allocate(1);
39  *p1 = 111; // Scribble something to make sure it doesn't mess up the list.
40  DCHECK(p1 != NULL);
41  EXPECT_EQ(mem_pool.total_allocated_bytes(), 16);
42  pool.Free(p1);
43 
44  // Allocating this should return p again.
45  for (int i = 0; i < 10; ++i) {
46  uint8_t* p2 = pool.Allocate(1);
47  *p2 = 111;
48  DCHECK(p1 == p2);
49  EXPECT_EQ(mem_pool.total_allocated_bytes(), 16);
50  pool.Free(p2);
51  }
52 
53  uint8_t* p2 = pool.Allocate(1);
54  *p2 = 111;
55  // p3 will cause a new allocation.
56  uint8_t* p3 = pool.Allocate(1);
57  *p3 = 111;
58  EXPECT_TRUE(p1 == p2);
59  EXPECT_TRUE(p1 != p3);
60  EXPECT_EQ(mem_pool.total_allocated_bytes(), 32);
61  pool.Free(p2);
62  pool.Free(p3);
63 
64  // We know have 2 1 byte allocations. Make a two byte allocation.
65  uint8_t* p4 = pool.Allocate(2);
66  memset(p4, 2, 123);
67  EXPECT_EQ(mem_pool.total_allocated_bytes(), 48);
68  EXPECT_TRUE(p4 != p1);
69  EXPECT_TRUE(p4 != p2);
70  EXPECT_TRUE(p4 != p3);
71  pool.Free(p4);
72 
73  // Everything's freed. Try grabbing the ones that have been allocated.
74  p1 = pool.Allocate(1);
75  *p1 = 123;
76  p2 = pool.Allocate(1);
77  *p2 = 123;
78  p3 = pool.Allocate(2);
79  memset(p3, 123, 2);
80  EXPECT_EQ(mem_pool.total_allocated_bytes(), 48);
81 
82  // Make another 1 byte allocation.
83  p4 = pool.Allocate(1);
84  *p4 = 1;
85  EXPECT_EQ(mem_pool.total_allocated_bytes(), 64);
86 
87  mem_pool.FreeAll();
88 }
89 
90 // In this test we make two allocations at increasing sizes and then we
91 // free both to prime the pool. Then, for a few iterations, we make the same allocations
92 // as we did to prime the pool in a random order. We validate that the returned
93 // allocation is one of the two original and the pool did not increase in size.
94 TEST(FreePoolTest, Loop) {
96  MemPool mem_pool(&tracker);
97  FreePool pool(&mem_pool);
98 
99  map<int, pair<uint8_t*, uint8_t*> > primed_allocations;
100  vector<int> allocation_sizes;
101 
102  int64_t expected_pool_size = 0;
103 
104  // Pick a non-power of 2 to exercise more code.
105  for (int size = 3; size < 1024 * 1024 * 1024; size *= 3) {
106  uint8_t* p1 = pool.Allocate(size);
107  uint8_t* p2 = pool.Allocate(size);
108  EXPECT_TRUE(p1 != NULL);
109  EXPECT_TRUE(p2 != NULL);
110  EXPECT_TRUE(p1 != p2);
111  memset(p1, 1, size); // Scribble the expected value (used below).
112  memset(p2, 1, size);
113  primed_allocations[size] = make_pair(p1, p2);
114  pool.Free(p1);
115  pool.Free(p2);
116  allocation_sizes.push_back(size);
117  }
118  expected_pool_size = mem_pool.total_allocated_bytes();
119 
120  for (int iters = 1; iters <= 5; ++iters) {
121  std::random_shuffle(allocation_sizes.begin(), allocation_sizes.end());
122  for (int i = 0; i < allocation_sizes.size(); ++i) {
123  uint8_t* p1 = pool.Allocate(allocation_sizes[i]);
124  uint8_t* p2 = pool.Allocate(allocation_sizes[i]);
125  EXPECT_TRUE(p1 != p2);
126  EXPECT_TRUE(p1 == primed_allocations[allocation_sizes[i]].first ||
127  p1 == primed_allocations[allocation_sizes[i]].second);
128  EXPECT_TRUE(p2 == primed_allocations[allocation_sizes[i]].first ||
129  p2 == primed_allocations[allocation_sizes[i]].second);
130  EXPECT_EQ(*p1, iters);
131  EXPECT_EQ(*p2, iters);
132  ++(*p1);
133  ++(*p2);
134  pool.Free(p1);
135  pool.Free(p2);
136  }
137  EXPECT_EQ(mem_pool.total_allocated_bytes(), expected_pool_size);
138  }
139 
140  mem_pool.FreeAll();
141 }
142 
143 TEST(FreePoolTest, ReAlloc) {
145  MemPool mem_pool(&tracker);
146  FreePool pool(&mem_pool);
147 
148  uint8_t* ptr = pool.Reallocate(NULL, 0);
149  ptr = pool.Reallocate(ptr, 0);
150  EXPECT_EQ(mem_pool.total_allocated_bytes(), 0);
151 
152  ptr = pool.Reallocate(ptr, 600);
153  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8);
154  uint8_t* ptr2 = pool.Reallocate(ptr, 200);
155  EXPECT_TRUE(ptr == ptr2);
156  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8);
157 
158  uint8_t* ptr3 = pool.Reallocate(ptr, 2000);
159  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8);
160  EXPECT_TRUE(ptr2 != ptr3);
161 
162  // The original 600 allocation should be there.
163  ptr = pool.Allocate(600);
164  EXPECT_EQ(mem_pool.total_allocated_bytes(), 1024 + 8 + 2048 + 8);
165 
166  mem_pool.FreeAll();
167 }
168 
169 }
170 
171 int main(int argc, char **argv) {
172  ::testing::InitGoogleTest(&argc, argv);
173  return RUN_ALL_TESTS();
174 }
175 
MemTracker tracker
int64_t total_allocated_bytes() const
Definition: mem-pool.h:148
TEST(AtomicTest, Basic)
Definition: atomic-test.cc:28
uint8_t * Reallocate(uint8_t *ptr, int size)
Definition: free-pool.h:102
int main(int argc, char **argv)
uint8_t * Allocate(int size)
Allocates a buffer of size.
Definition: free-pool.h:54
void FreeAll()
Definition: mem-pool.cc:73
void Free(uint8_t *ptr)
Definition: free-pool.h:82
ObjectPool pool
This class is thread-safe.
Definition: mem-tracker.h:61