1 | // |
2 | // MemoryPoolTest.cpp |
3 | // |
4 | // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. |
5 | // and Contributors. |
6 | // |
7 | // SPDX-License-Identifier: BSL-1.0 |
8 | // |
9 | |
10 | |
11 | #include "MemoryPoolTest.h" |
12 | #include "Poco/CppUnit/TestCaller.h" |
13 | #include "Poco/CppUnit/TestSuite.h" |
14 | #include "Poco/MemoryPool.h" |
15 | #include "Poco/Stopwatch.h" |
16 | #include <vector> |
17 | #include <cstring> |
18 | #include <iostream> |
19 | |
20 | |
21 | using Poco::MemoryPool; |
22 | |
23 | |
24 | MemoryPoolTest::MemoryPoolTest(const std::string& rName): CppUnit::TestCase(rName) |
25 | { |
26 | } |
27 | |
28 | |
29 | MemoryPoolTest::~MemoryPoolTest() |
30 | { |
31 | } |
32 | |
33 | |
34 | void MemoryPoolTest::testMemoryPool() |
35 | { |
36 | MemoryPool pool1(100, 0, 10); |
37 | |
38 | assertTrue (pool1.blockSize() == 100); |
39 | assertTrue (pool1.allocated() == 0); |
40 | assertTrue (pool1.available() == 0); |
41 | |
42 | std::vector<void*> ptrs; |
43 | for (int i = 0; i < 10; ++i) |
44 | { |
45 | ptrs.push_back(pool1.get()); |
46 | assertTrue (pool1.allocated() == i + 1); |
47 | assertTrue (pool1.available() == 0); |
48 | } |
49 | |
50 | try |
51 | { |
52 | pool1.get(); |
53 | fail("pool exhausted - must throw exception" ); |
54 | } |
55 | catch (Poco::OutOfMemoryException&) |
56 | { |
57 | } |
58 | |
59 | int av = 0; |
60 | for (std::vector<void*>::iterator it = ptrs.begin(); it != ptrs.end(); ++it) |
61 | { |
62 | pool1.release(*it); |
63 | ++av; |
64 | assertTrue (pool1.available() == av); |
65 | } |
66 | |
67 | MemoryPool pool2(32, 5, 10); |
68 | assertTrue (pool2.available() == 5); |
69 | assertTrue (pool2.blockSize() == 32); |
70 | assertTrue (pool2.allocated() == 5); |
71 | } |
72 | |
73 | |
74 | namespace |
75 | { |
76 | |
77 | template<typename T> |
78 | bool fastMemPoolTest(int n) |
79 | { |
80 | bool ret = true; |
81 | std::vector<T*> vec(n, (T*)0); |
82 | Poco::FastMemoryPool<T> pool(sizeof(T*), vec.size()/2); |
83 | for (int i = 0; i < vec.size(); ++i) |
84 | { |
85 | vec[i] = new (pool.get()) T(i); |
86 | } |
87 | |
88 | for (int i = 0; i < vec.size(); ++i) |
89 | { |
90 | ret = ret && (vec[i] && *vec[i] == i); |
91 | } |
92 | |
93 | for (int i = 0; i < vec.size(); ++i) |
94 | { |
95 | pool.release(vec[i]); |
96 | } |
97 | |
98 | return ret; |
99 | } |
100 | |
101 | template <typename T> |
102 | bool fastMemPoolTestCustom(int n, const T& val) |
103 | { |
104 | bool ret = true; |
105 | std::vector<T*> vec(n, (T*)0); |
106 | Poco::FastMemoryPool<T> pool(sizeof(T*), vec.size()/2); |
107 | for (int i = 0; i < vec.size(); ++i) |
108 | { |
109 | vec[i] = new (pool.get()) T(val); |
110 | } |
111 | |
112 | for (int i = 0; i < vec.size(); ++i) |
113 | { |
114 | ret = ret && (vec[i] && *vec[i] == val); |
115 | } |
116 | |
117 | for (int i = 0; i < vec.size(); ++i) |
118 | { |
119 | pool.release(vec[i]); |
120 | } |
121 | |
122 | return ret; |
123 | } |
124 | |
125 | struct Custom |
126 | { |
127 | virtual ~Custom() {} |
128 | bool operator ==(const Custom& other) const |
129 | { |
130 | return i == other.i && s == other.s; |
131 | } |
132 | int i = 42; |
133 | std::string s = "abc" ; |
134 | }; |
135 | |
136 | struct CustomChild1: virtual public Custom |
137 | { |
138 | bool operator ==(const CustomChild1& other) const |
139 | { |
140 | return i == other.i && s == other.s && j == other.j; |
141 | } |
142 | int j = 0; |
143 | }; |
144 | |
145 | struct CustomChild2: virtual public Custom |
146 | { |
147 | bool operator ==(const CustomChild2& other) const |
148 | { |
149 | return i == other.i && s == other.s && k == other.k; |
150 | } |
151 | int k = 0; |
152 | }; |
153 | |
154 | struct CustomGrandChild: public CustomChild1, CustomChild2 |
155 | { |
156 | bool operator ==(const CustomGrandChild& other) const |
157 | { |
158 | return i == other.i && s == other.s && |
159 | j == other.j && k == other.k && l == other.l; |
160 | } |
161 | int l = 0; |
162 | }; |
163 | |
164 | } |
165 | |
166 | |
167 | void MemoryPoolTest::testFastMemoryPool() |
168 | { |
169 | int blocks = 10; |
170 | Poco::FastMemoryPool<int> fastIntPool(blocks); |
171 | Poco::FastMemoryPool<std::string> fastStringPool(blocks); |
172 | |
173 | std::vector<int*> intVec(blocks, (int*)0); |
174 | std::vector<std::string*> strVec(blocks); |
175 | |
176 | for (int i = 0; i < blocks; ++i) |
177 | { |
178 | intVec[i] = new (fastIntPool.get()) int(i); |
179 | strVec[i] = new (fastStringPool.get()) std::string(std::to_string(i)); |
180 | } |
181 | |
182 | for (int i = 0; i < blocks; ++i) |
183 | { |
184 | assertTrue (intVec[i] && *intVec[i] == i); |
185 | assertTrue (strVec[i] && *strVec[i] == std::to_string(i)); |
186 | } |
187 | |
188 | for (int i = 0; i < blocks; ++i) |
189 | { |
190 | fastIntPool.release(intVec[i]); |
191 | fastStringPool.release(strVec[i]); |
192 | } |
193 | |
194 | int sz = 5; |
195 | assertTrue (fastMemPoolTest<char>(sz)); |
196 | assertTrue (fastMemPoolTest<signed char>(sz)); |
197 | assertTrue (fastMemPoolTest<unsigned char>(sz)); |
198 | assertTrue (fastMemPoolTest<short>(sz)); |
199 | assertTrue (fastMemPoolTest<unsigned short>(sz)); |
200 | assertTrue (fastMemPoolTest<int>(sz)); |
201 | assertTrue (fastMemPoolTest<unsigned int>(sz)); |
202 | assertTrue (fastMemPoolTest<long>(sz)); |
203 | assertTrue (fastMemPoolTest<unsigned long>(sz)); |
204 | |
205 | std::string str = "123abc" ; |
206 | assertTrue (fastMemPoolTestCustom(sz, str)); |
207 | |
208 | Custom c; |
209 | assertTrue (fastMemPoolTestCustom(sz, c)); |
210 | |
211 | CustomChild1 c1; |
212 | assertTrue (fastMemPoolTestCustom(sz, c1)); |
213 | |
214 | CustomChild2 c2; |
215 | assertTrue (fastMemPoolTestCustom(sz, c2)); |
216 | |
217 | CustomGrandChild gc; |
218 | assertTrue (fastMemPoolTestCustom(sz, gc)); |
219 | } |
220 | |
221 | |
222 | void MemoryPoolTest::memoryPoolBenchmark() |
223 | { |
224 | Poco::Stopwatch sw; |
225 | |
226 | int reps = 1000000; |
227 | std::vector<int*> iVec(reps, (int*)0); |
228 | Poco::FastMemoryPool<int> fastPool(reps); |
229 | sw.restart(); |
230 | for (int i = 0; i < reps; ++i) |
231 | { |
232 | iVec[i] = new (fastPool.get()) int(i); |
233 | } |
234 | sw.stop(); |
235 | std::cout << '\n' << reps << "x\n" ; |
236 | std::cout << "get()\t\tFastMemoryPool=" << sw.elapsed() / 1000 << std::endl; |
237 | |
238 | for (int i = 0; i < reps; ++i) |
239 | { |
240 | assertTrue(*iVec[i] == i); |
241 | } |
242 | |
243 | sw.restart(); |
244 | for (int i = 0; i < reps; ++i) |
245 | { |
246 | fastPool.release(iVec[i]); |
247 | } |
248 | sw.stop(); |
249 | std::cout << "release()\tFastMemoryPool=" << sw.elapsed() / 1000 << std::endl; |
250 | |
251 | MemoryPool pool(sizeof(int*), reps); |
252 | sw.start(); |
253 | for (int i = 0; i < reps; ++i) |
254 | { |
255 | iVec[i] = new (pool.get()) int(i); |
256 | } |
257 | sw.stop(); |
258 | std::cout << "get()\t\tMemoryPool=" << sw.elapsed() / 1000 << std::endl; |
259 | |
260 | for (int i = 0; i < reps; ++i) |
261 | { |
262 | assertTrue(iVec[i] && *iVec[i] == i); |
263 | } |
264 | |
265 | sw.restart(); |
266 | for (int i = 0; i < reps; ++i) |
267 | { |
268 | pool.release(iVec[i]); |
269 | } |
270 | sw.stop(); |
271 | std::cout << "release()\tMemoryPool=" << sw.elapsed() / 1000 << std::endl; |
272 | } |
273 | |
274 | |
275 | void MemoryPoolTest::setUp() |
276 | { |
277 | } |
278 | |
279 | |
280 | void MemoryPoolTest::tearDown() |
281 | { |
282 | } |
283 | |
284 | |
285 | CppUnit::Test* MemoryPoolTest::suite() |
286 | { |
287 | CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MemoryPoolTest" ); |
288 | |
289 | CppUnit_addTest(pSuite, MemoryPoolTest, testMemoryPool); |
290 | CppUnit_addTest(pSuite, MemoryPoolTest, testFastMemoryPool); |
291 | //CppUnit_addTest(pSuite, MemoryPoolTest, memoryPoolBenchmark); |
292 | |
293 | return pSuite; |
294 | } |
295 | |