Skip to content

Commit 370c281

Browse files
Merge pull request #1347 from lplewa/pool_by_ptr_benchmark
Add stacked pool benchmark
2 parents d5d2317 + 36e5929 commit 370c281

File tree

7 files changed

+248
-20
lines changed

7 files changed

+248
-20
lines changed

benchmark/benchmark.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,39 @@ UMF_BENCHMARK_REGISTER_F(peak_alloc_benchmark, scalable_pool_uniform)
220220

221221
#endif
222222

223+
// stacked pool benchmarks
224+
225+
UMF_BENCHMARK_TEMPLATE_DEFINE(multiple_malloc_free_benchmark,
226+
disjoint_pool_stack_fix, fixed_alloc_size,
227+
pool_stacked_allocator<os_provider>);
228+
229+
UMF_BENCHMARK_REGISTER_F(multiple_malloc_free_benchmark,
230+
disjoint_pool_stack_fix)
231+
->Apply(&default_multiple_alloc_fix_size)
232+
->Apply(&multithreaded);
233+
234+
UMF_BENCHMARK_TEMPLATE_DEFINE(multiple_malloc_free_benchmark,
235+
disjoint_pool_stack_uniform, uniform_alloc_size,
236+
pool_stacked_allocator<os_provider>);
237+
UMF_BENCHMARK_REGISTER_F(multiple_malloc_free_benchmark,
238+
disjoint_pool_stack_uniform)
239+
->Apply(&default_multiple_alloc_uniform_size)
240+
->Apply(&multithreaded);
241+
242+
UMF_BENCHMARK_TEMPLATE_DEFINE(peak_alloc_benchmark, disjoint_pool_stack_fix,
243+
fixed_alloc_size,
244+
pool_stacked_allocator<os_provider>);
245+
UMF_BENCHMARK_REGISTER_F(peak_alloc_benchmark, disjoint_pool_stack_fix)
246+
->Apply(&default_multiple_alloc_fix_size)
247+
->Apply(&multithreaded);
248+
249+
UMF_BENCHMARK_TEMPLATE_DEFINE(peak_alloc_benchmark, disjoint_pool_stack_uniform,
250+
uniform_alloc_size,
251+
pool_stacked_allocator<os_provider>);
252+
UMF_BENCHMARK_REGISTER_F(peak_alloc_benchmark, disjoint_pool_stack_uniform)
253+
->Apply(&default_multiple_alloc_uniform_size)
254+
->Apply(&multithreaded);
255+
223256
//BENCHMARK_MAIN();
224257
int main(int argc, char **argv) {
225258
if (initAffinityMask()) {

benchmark/benchmark.hpp

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#include <list>
7474
#include <malloc.h>
7575
#include <random>
76+
#include <stdexcept>
7677

7778
#include <benchmark/benchmark.h>
7879
#include <umf/memory_pool.h>
@@ -209,32 +210,71 @@ class provider_allocator : public allocator_interface {
209210
// TODO: assert Pool to be a pool_interface<provider_interface>.
210211
template <typename Pool> class pool_allocator : public allocator_interface {
211212
public:
212-
unsigned SetUp(::benchmark::State &state, unsigned argPos) override {
213+
virtual unsigned SetUp(::benchmark::State &state,
214+
unsigned argPos) override {
213215
pool.SetUp(state);
214216
return argPos;
215217
}
216218

217-
void preBench(::benchmark::State &state) override { pool.preBench(state); }
218-
void postBench(::benchmark::State &state) override {
219+
virtual void preBench(::benchmark::State &state) override {
220+
pool.preBench(state);
221+
}
222+
virtual void postBench(::benchmark::State &state) override {
219223
pool.postBench(state);
220224
}
221225

222-
void TearDown(::benchmark::State &state) override { pool.TearDown(state); }
226+
virtual void TearDown(::benchmark::State &state) override {
227+
pool.TearDown(state);
228+
}
223229

224-
void *benchAlloc(size_t size) override {
230+
virtual void *benchAlloc(size_t size) override {
225231
return umfPoolMalloc(pool.pool, size);
226232
}
227233

228-
void benchFree(void *ptr, [[maybe_unused]] size_t size) override {
234+
virtual void benchFree(void *ptr, [[maybe_unused]] size_t size) override {
229235
umfPoolFree(pool.pool, ptr);
230236
}
231237

232238
static std::string name() { return Pool::name(); }
233239

234-
private:
240+
protected:
235241
Pool pool;
236242
};
237243

244+
template <typename Provider>
245+
class pool_stacked_allocator
246+
: public pool_allocator<disjoint_pool_stack<Provider>> {
247+
using base = pool_allocator<disjoint_pool_stack<Provider>>;
248+
249+
public:
250+
virtual void preBench([[maybe_unused]] ::benchmark::State &state) override {
251+
// we do not measure fragmentation for stack pools
252+
}
253+
virtual void
254+
postBench([[maybe_unused]] ::benchmark::State &state) override {
255+
// we do not measure fragmentation for stack pools
256+
}
257+
void *benchAlloc(size_t size) override {
258+
static thread_local int counter = 0;
259+
static auto pool_number = base::pool.pools.size();
260+
// stacked pools has limited space, so we might need a few
261+
// tries to find one with free space
262+
auto retry = pool_number;
263+
while (retry--) {
264+
void *ptr = umfPoolMalloc(
265+
base::pool.pools[(++counter % pool_number)], size);
266+
if (ptr != NULL) {
267+
return ptr;
268+
}
269+
}
270+
return NULL;
271+
}
272+
273+
void benchFree(void *ptr, [[maybe_unused]] size_t size) override {
274+
umfFree(ptr);
275+
}
276+
};
277+
238278
template <typename Size, typename Allocator>
239279
struct benchmark_interface : public benchmark::Fixture {
240280
int parseArgs(::benchmark::State &state, int argPos) {

benchmark/benchmark_umf.hpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,142 @@ struct disjoint_pool : public pool_interface<Provider> {
317317
}
318318
};
319319

320+
// benchmark tracking provider, by creating big number pools(2^7) stacked
321+
template <typename Provider>
322+
struct disjoint_pool_stack : public disjoint_pool<Provider> {
323+
using base = disjoint_pool<Provider>;
324+
325+
std::vector<umf_memory_provider_handle_t> providers;
326+
std::vector<umf_memory_pool_handle_t> pools;
327+
std::vector<void *> pool_ptrs;
328+
329+
static constexpr size_t firstPoolSize = 2ull * 1024 * 1024 * 1024; // 2GB
330+
static constexpr size_t levels = 7;
331+
332+
void SetUp(::benchmark::State &state) {
333+
base::provider.SetUp(state);
334+
if (state.thread_index() != 0) {
335+
return;
336+
}
337+
338+
providers.push_back(base::provider.provider);
339+
base::provider.provider = nullptr;
340+
341+
auto params = base::getParams(state);
342+
umf_memory_pool_handle_t rootPool = nullptr;
343+
auto umf_result = umfPoolCreate(base::getOps(state), providers[0],
344+
params.get(), 0, &rootPool);
345+
if (umf_result != UMF_RESULT_SUCCESS) {
346+
state.SkipWithError("umfPoolCreate() failed");
347+
return;
348+
}
349+
350+
pools.push_back(rootPool); // root pool
351+
352+
umf_fixed_memory_provider_params_handle_t params_fixed = nullptr;
353+
umf_result = umfFixedMemoryProviderParamsCreate(
354+
&params_fixed, (void *)0x1, 0x1); // dummy
355+
356+
size_t poolSize = firstPoolSize;
357+
size_t level_start = 0;
358+
size_t level_pools = 1;
359+
360+
for (size_t level = 1; level < levels; ++level) {
361+
// split each pools for 3 parts - two for children, and third from other allocations from this pool
362+
poolSize /= 3;
363+
size_t new_level_pools = level_pools * 2;
364+
365+
for (size_t parent_idx = 0; parent_idx < level_pools;
366+
++parent_idx) {
367+
umf_memory_pool_handle_t parent_pool =
368+
pools[level_start + parent_idx];
369+
370+
for (int child = 0; child < 2; ++child) {
371+
void *ptr = umfPoolMalloc(parent_pool, poolSize);
372+
if (!ptr) {
373+
state.SkipWithError("umfPoolMalloc() failed");
374+
return;
375+
}
376+
pool_ptrs.push_back(ptr);
377+
378+
umf_result = umfFixedMemoryProviderParamsSetMemory(
379+
params_fixed, ptr, poolSize);
380+
umf_memory_provider_handle_t prov;
381+
umf_result = umfMemoryProviderCreate(
382+
umfFixedMemoryProviderOps(), params_fixed, &prov);
383+
if (umf_result != UMF_RESULT_SUCCESS) {
384+
state.SkipWithError("umfMemoryProviderCreate() failed");
385+
return;
386+
}
387+
providers.push_back(prov);
388+
389+
umf_memory_pool_handle_t newPool;
390+
umf_result = umfPoolCreate(base::getOps(state), prov,
391+
params.get(), 0, &newPool);
392+
if (umf_result != UMF_RESULT_SUCCESS) {
393+
state.SkipWithError("umfPoolCreate() failed");
394+
return;
395+
}
396+
397+
pools.push_back(newPool);
398+
}
399+
}
400+
401+
level_start += level_pools;
402+
level_pools = new_level_pools;
403+
}
404+
405+
umfFixedMemoryProviderParamsDestroy(params_fixed);
406+
}
407+
408+
void TearDown(::benchmark::State &state) {
409+
if (state.thread_index() != 0) {
410+
return;
411+
}
412+
413+
size_t pool_index = pools.size();
414+
size_t provider_index = providers.size();
415+
size_t ptr_index = pool_ptrs.size();
416+
417+
// Go from last level to first (excluding level 0, root)
418+
for (int level = levels - 1; level > 0; --level) {
419+
size_t level_pools = 1ull << level; // 2^level pools
420+
421+
// Destroy pools
422+
for (size_t i = 0; i < level_pools; ++i) {
423+
--pool_index;
424+
umfPoolDestroy(pools[pool_index]);
425+
}
426+
427+
// Destroy providers and free pointers
428+
for (size_t i = 0; i < level_pools; ++i) {
429+
--provider_index;
430+
umfMemoryProviderDestroy(providers[provider_index]);
431+
432+
--ptr_index;
433+
void *ptr = pool_ptrs[ptr_index];
434+
if (ptr) {
435+
umfFree(ptr);
436+
}
437+
}
438+
}
439+
440+
// Root pool and provider
441+
umfPoolDestroy(pools[0]);
442+
umfMemoryProviderDestroy(providers[0]);
443+
444+
pools.clear();
445+
providers.clear();
446+
pool_ptrs.clear();
447+
448+
base::TearDown(state);
449+
}
450+
451+
static std::string name() {
452+
return "disjoint_pool_stacked<" + Provider::name() + ">";
453+
}
454+
};
455+
320456
#ifdef UMF_POOL_JEMALLOC_ENABLED
321457
template <typename Provider>
322458
struct jemalloc_pool : public pool_interface<Provider> {

src/libumf.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ EXPORTS
133133
umfFixedMemoryProviderOps
134134
umfFixedMemoryProviderParamsCreate
135135
umfFixedMemoryProviderParamsDestroy
136+
umfFixedMemoryProviderParamsSetMemory
136137
umfLevelZeroMemoryProviderParamsSetFreePolicy
137138
umfLevelZeroMemoryProviderParamsSetDeviceOrdinal
138139
; Added in UMF_0.12

src/libumf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ UMF_0.11 {
131131
umfFixedMemoryProviderOps;
132132
umfFixedMemoryProviderParamsCreate;
133133
umfFixedMemoryProviderParamsDestroy;
134+
umfFixedMemoryProviderParamsSetMemory;
134135
umfLevelZeroMemoryProviderParamsSetFreePolicy;
135136
umfLevelZeroMemoryProviderParamsSetDeviceOrdinal;
136137
} UMF_0.10;

0 commit comments

Comments
 (0)