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
21using Poco::MemoryPool;
22
23
24MemoryPoolTest::MemoryPoolTest(const std::string& rName): CppUnit::TestCase(rName)
25{
26}
27
28
29MemoryPoolTest::~MemoryPoolTest()
30{
31}
32
33
34void 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
74namespace
75{
76
77template<typename T>
78bool 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
101template <typename T>
102bool 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
125struct 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
136struct 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
145struct 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
154struct 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
167void 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
222void 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
275void MemoryPoolTest::setUp()
276{
277}
278
279
280void MemoryPoolTest::tearDown()
281{
282}
283
284
285CppUnit::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