Skip to content

Commit aef7ae7

Browse files
authored
Merge pull request #984 from lplewa/uniqe
use unique_ptr instead of constructor/destructor in benchmarks
2 parents 3dc6734 + 36d134c commit aef7ae7

File tree

3 files changed

+79
-67
lines changed

3 files changed

+79
-67
lines changed

benchmark/benchmark.cpp

Lines changed: 50 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,27 @@ struct glibc_malloc : public allocator_interface {
3737
};
3838

3939
struct os_provider : public provider_interface {
40-
umf_os_memory_provider_params_handle_t params = NULL;
41-
os_provider() {
42-
umfOsMemoryProviderParamsCreate(&params);
43-
return;
44-
}
45-
46-
~os_provider() {
47-
if (params != NULL) {
48-
umfOsMemoryProviderParamsDestroy(params);
40+
provider_interface::params_ptr
41+
getParams(::benchmark::State &state) override {
42+
umf_os_memory_provider_params_handle_t raw_params = nullptr;
43+
umfOsMemoryProviderParamsCreate(&raw_params);
44+
if (!raw_params) {
45+
state.SkipWithError("Failed to create os provider params");
46+
return {nullptr, [](void *) {}};
4947
}
48+
49+
// Use a lambda as the custom deleter
50+
auto deleter = [](void *p) {
51+
auto handle =
52+
static_cast<umf_os_memory_provider_params_handle_t>(p);
53+
umfOsMemoryProviderParamsDestroy(handle);
54+
};
55+
56+
return {static_cast<void *>(raw_params), deleter};
5057
}
5158

52-
void *getParams() override { return params; }
53-
umf_memory_provider_ops_t *getOps() override {
59+
umf_memory_provider_ops_t *
60+
getOps([[maybe_unused]] ::benchmark::State &state) override {
5461
return umfOsMemoryProviderOps();
5562
}
5663
static std::string name() { return "os_provider"; }
@@ -62,73 +69,60 @@ struct proxy_pool : public pool_interface<Provider> {
6269
getOps([[maybe_unused]] ::benchmark::State &state) override {
6370
return umfProxyPoolOps();
6471
}
65-
void *getParams([[maybe_unused]] ::benchmark::State &state) override {
66-
return nullptr;
67-
}
72+
6873
static std::string name() { return "proxy_pool<" + Provider::name() + ">"; }
6974
};
7075

7176
#ifdef UMF_POOL_DISJOINT_ENABLED
7277
template <typename Provider>
7378
struct disjoint_pool : public pool_interface<Provider> {
74-
umf_disjoint_pool_params_handle_t disjoint_memory_pool_params;
79+
umf_memory_pool_ops_t *
80+
getOps([[maybe_unused]] ::benchmark::State &state) override {
81+
return umfDisjointPoolOps();
82+
}
7583

76-
disjoint_pool() {
77-
disjoint_memory_pool_params = NULL;
78-
auto ret = umfDisjointPoolParamsCreate(&disjoint_memory_pool_params);
84+
typename pool_interface<Provider>::params_ptr
85+
getParams(::benchmark::State &state) override {
86+
umf_disjoint_pool_params_handle_t raw_params = nullptr;
87+
auto ret = umfDisjointPoolParamsCreate(&raw_params);
7988
if (ret != UMF_RESULT_SUCCESS) {
80-
return;
89+
state.SkipWithError("Failed to create disjoint pool params");
90+
return {nullptr, [](void *) {}};
8191
}
8292

83-
// those function should never fail, so error handling is minimal.
84-
ret = umfDisjointPoolParamsSetSlabMinSize(disjoint_memory_pool_params,
85-
4096);
86-
if (ret != UMF_RESULT_SUCCESS) {
87-
goto err;
88-
}
93+
typename pool_interface<Provider>::params_ptr params(
94+
raw_params, [](void *p) {
95+
umfDisjointPoolParamsDestroy(
96+
static_cast<umf_disjoint_pool_params_handle_t>(p));
97+
});
8998

90-
ret = umfDisjointPoolParamsSetCapacity(disjoint_memory_pool_params, 4);
99+
ret = umfDisjointPoolParamsSetSlabMinSize(raw_params, 4096);
91100
if (ret != UMF_RESULT_SUCCESS) {
92-
goto err;
101+
state.SkipWithError("Failed to set slab min size");
102+
return {nullptr, [](void *) {}};
93103
}
94104

95-
ret = umfDisjointPoolParamsSetMinBucketSize(disjoint_memory_pool_params,
96-
4096);
105+
ret = umfDisjointPoolParamsSetCapacity(raw_params, 4);
97106
if (ret != UMF_RESULT_SUCCESS) {
98-
goto err;
107+
state.SkipWithError("Failed to set capacity");
108+
return {nullptr, [](void *) {}};
99109
}
100110

101-
ret = umfDisjointPoolParamsSetMaxPoolableSize(
102-
disjoint_memory_pool_params, 4096 * 16);
103-
111+
ret = umfDisjointPoolParamsSetMinBucketSize(raw_params, 4096);
104112
if (ret != UMF_RESULT_SUCCESS) {
105-
goto err;
113+
state.SkipWithError("Failed to set min bucket size");
114+
return {nullptr, [](void *) {}};
106115
}
107-
return;
108-
err:
109116

110-
umfDisjointPoolParamsDestroy(disjoint_memory_pool_params);
111-
disjoint_memory_pool_params = NULL;
112-
}
113-
114-
~disjoint_pool() {
115-
if (disjoint_memory_pool_params != NULL) {
116-
umfDisjointPoolParamsDestroy(disjoint_memory_pool_params);
117+
ret = umfDisjointPoolParamsSetMaxPoolableSize(raw_params, 4096 * 16);
118+
if (ret != UMF_RESULT_SUCCESS) {
119+
state.SkipWithError("Failed to set max poolable size");
120+
return {nullptr, [](void *) {}};
117121
}
118-
}
119122

120-
umf_memory_pool_ops_t *
121-
getOps([[maybe_unused]] ::benchmark::State &state) override {
122-
return umfDisjointPoolOps();
123+
return params;
123124
}
124-
void *getParams([[maybe_unused]] ::benchmark::State &state) override {
125125

126-
if (disjoint_memory_pool_params == NULL) {
127-
state.SkipWithError("Failed to create disjoint pool params");
128-
}
129-
130-
return disjoint_memory_pool_params;
131-
}
132126
static std::string name() {
133127
return "disjoint_pool<" + Provider::name() + ">";
134128
}
@@ -142,9 +136,7 @@ struct jemalloc_pool : public pool_interface<Provider> {
142136
getOps([[maybe_unused]] ::benchmark::State &state) override {
143137
return umfJemallocPoolOps();
144138
}
145-
void *getParams([[maybe_unused]] ::benchmark::State &state) override {
146-
return NULL;
147-
}
139+
148140
static std::string name() {
149141
return "jemalloc_pool<" + Provider::name() + ">";
150142
}
@@ -158,10 +150,7 @@ struct scalable_pool : public pool_interface<Provider> {
158150
getOps([[maybe_unused]] ::benchmark::State &state) override {
159151
return umfScalablePoolOps();
160152
}
161-
virtual void *
162-
getParams([[maybe_unused]] ::benchmark::State &state) override {
163-
return NULL;
164-
}
153+
165154
static std::string name() {
166155
return "scalable_pool<" + Provider::name() + ">";
167156
}

benchmark/benchmark.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,14 @@ class alloc_benchmark : public benchmark_interface<Size, Alloc> {
232232
state.ResumeTiming();
233233
}
234234
}
235+
235236
static std::vector<std::string> argsName() {
236237
auto n = benchmark_interface<Size, Alloc>::argsName();
237238
std::vector<std::string> res = {"max_allocs", "pre_allocs"};
238239
res.insert(res.end(), n.begin(), n.end());
239240
return res;
240241
}
242+
241243
static std::string name() { return base::name() + "/alloc"; }
242244
static int64_t iterations() { return 200000; }
243245

@@ -320,13 +322,16 @@ class multiple_malloc_free_benchmark : public alloc_benchmark<Size, Alloc> {
320322
static std::string name() {
321323
return base::base::name() + "/multiple_malloc_free";
322324
}
325+
323326
static std::vector<std::string> argsName() {
324327
auto n = benchmark_interface<Size, Alloc>::argsName();
325328
std::vector<std::string> res = {"max_allocs"};
326329
res.insert(res.end(), n.begin(), n.end());
327330
return res;
328331
}
332+
329333
static int64_t iterations() { return 2000; }
334+
330335
std::default_random_engine generator;
331336
distribution dist;
332337
};
@@ -352,9 +357,11 @@ class provider_allocator : public allocator_interface {
352357
}
353358
return ptr;
354359
}
360+
355361
void benchFree(void *ptr, size_t size) override {
356362
umfMemoryProviderFree(provider.provider, ptr, size);
357363
}
364+
358365
static std::string name() { return Provider::name(); }
359366

360367
private:
@@ -374,6 +381,7 @@ template <typename Pool> class pool_allocator : public allocator_interface {
374381
virtual void *benchAlloc(size_t size) override {
375382
return umfPoolMalloc(pool.pool, size);
376383
}
384+
377385
virtual void benchFree(void *ptr, [[maybe_unused]] size_t size) override {
378386
umfPoolFree(pool.pool, ptr);
379387
}

benchmark/benchmark_interfaces.hpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*
77
*/
88

9+
#include <memory>
910
#include <string>
1011
#include <thread>
1112
#include <vector>
@@ -39,6 +40,7 @@ struct benchmark_interface : public benchmark::Fixture {
3940
int argPos = alloc_size.SetUp(state, 0);
4041
allocator.SetUp(state, argPos);
4142
}
43+
4244
void TearDown(::benchmark::State &state) {
4345
alloc_size.TearDown(state);
4446
allocator.TearDown(state);
@@ -54,20 +56,24 @@ struct benchmark_interface : public benchmark::Fixture {
5456
res.insert(res.end(), a.begin(), a.end());
5557
return res;
5658
}
59+
5760
static std::string name() { return Allocator::name(); }
5861
static int64_t iterations() { return 10000; }
5962
Size alloc_size;
6063
Allocator allocator;
6164
};
6265

6366
struct provider_interface {
67+
using params_ptr = std::unique_ptr<void, void (*)(void *)>;
68+
6469
umf_memory_provider_handle_t provider = NULL;
6570
virtual void SetUp(::benchmark::State &state) {
6671
if (state.thread_index() != 0) {
6772
return;
6873
}
74+
auto params = getParams(state);
6975
auto umf_result =
70-
umfMemoryProviderCreate(getOps(), getParams(), &provider);
76+
umfMemoryProviderCreate(getOps(state), params.get(), &provider);
7177
if (umf_result != UMF_RESULT_SUCCESS) {
7278
state.SkipWithError("umfMemoryProviderCreate() failed");
7379
}
@@ -83,21 +89,30 @@ struct provider_interface {
8389
}
8490
}
8591

86-
virtual umf_memory_provider_ops_t *getOps() { return nullptr; }
87-
virtual void *getParams() { return nullptr; }
92+
virtual umf_memory_provider_ops_t *
93+
getOps([[maybe_unused]] ::benchmark::State &state) {
94+
return nullptr;
95+
}
96+
97+
virtual params_ptr getParams([[maybe_unused]] ::benchmark::State &state) {
98+
return {nullptr, [](void *) {}};
99+
}
88100
};
89101

90102
template <typename T,
91103
typename =
92104
std::enable_if_t<std::is_base_of<provider_interface, T>::value>>
93105
struct pool_interface {
106+
using params_ptr = std::unique_ptr<void, void (*)(void *)>;
107+
94108
virtual void SetUp(::benchmark::State &state) {
95109
provider.SetUp(state);
96110
if (state.thread_index() != 0) {
97111
return;
98112
}
113+
auto params = getParams(state);
99114
auto umf_result = umfPoolCreate(getOps(state), provider.provider,
100-
getParams(state), 0, &pool);
115+
params.get(), 0, &pool);
101116
if (umf_result != UMF_RESULT_SUCCESS) {
102117
state.SkipWithError("umfPoolCreate() failed");
103118
}
@@ -121,8 +136,8 @@ struct pool_interface {
121136
getOps([[maybe_unused]] ::benchmark::State &state) {
122137
return nullptr;
123138
}
124-
virtual void *getParams([[maybe_unused]] ::benchmark::State &state) {
125-
return nullptr;
139+
virtual params_ptr getParams([[maybe_unused]] ::benchmark::State &state) {
140+
return {nullptr, [](void *) {}};
126141
}
127142
T provider;
128143
umf_memory_pool_handle_t pool;

0 commit comments

Comments
 (0)