Skip to content

Commit 95b4c6d

Browse files
authored
Merge pull request #1377 from KFilipek/disjoint-nonnull
[disjoint] Set default parameters for disjoint pool
2 parents 00245bb + b350c05 commit 95b4c6d

File tree

5 files changed

+155
-9
lines changed

5 files changed

+155
-9
lines changed

examples/ipc_level_zero/ipc_level_zero.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ int create_level_zero_pool(ze_context_handle_t context,
7676
goto provider_destroy;
7777
}
7878

79+
// Set max poolable size to 0
80+
umf_result = umfDisjointPoolParamsSetMaxPoolableSize(disjoint_params, 0);
81+
if (umf_result != UMF_RESULT_SUCCESS) {
82+
fprintf(stderr, "ERROR: Failed to set max poolable size!\n");
83+
goto provider_destroy;
84+
}
85+
7986
// create pool
8087
umf_pool_create_flags_t flags = UMF_POOL_CREATE_FLAG_OWN_PROVIDER;
8188
umf_result = umfPoolCreate(umfDisjointPoolOps(), provider, disjoint_params,

include/umf/pools/pool_disjoint.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ umf_result_t
5353
umfDisjointPoolParamsDestroy(umf_disjoint_pool_params_handle_t hParams);
5454

5555
/// @brief Set minimum allocation size that will be requested from the memory provider.
56+
/// @details Default value for minimum size of slab's is 64KB.
5657
/// @param hParams handle to the parameters of the disjoint pool.
5758
/// @param slabMinSize minimum allocation size.
5859
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
@@ -61,6 +62,7 @@ umfDisjointPoolParamsSetSlabMinSize(umf_disjoint_pool_params_handle_t hParams,
6162
size_t slabMinSize);
6263

6364
/// @brief Set size limit for allocations that are subject to pooling.
65+
/// @details Default value for maximum poolable size is 2MB.
6466
/// @param hParams handle to the parameters of the disjoint pool.
6567
/// @param maxPoolableSize maximum poolable size.
6668
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
@@ -69,6 +71,7 @@ umf_result_t umfDisjointPoolParamsSetMaxPoolableSize(
6971

7072
/// @brief Set maximum capacity of each bucket. Each bucket will hold a
7173
/// max of \p maxCapacity unfreed slabs.
74+
/// @details Default value for capacity is 4.
7275
/// @param hParams handle to the parameters of the disjoint pool.
7376
/// @param maxCapacity maximum capacity of each bucket.
7477
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
@@ -77,6 +80,7 @@ umfDisjointPoolParamsSetCapacity(umf_disjoint_pool_params_handle_t hParams,
7780
size_t maxCapacity);
7881

7982
/// @brief Set minimum bucket allocation size.
83+
/// @details Default value for minimum bucket size is 8.
8084
/// @param hParams handle to the parameters of the disjoint pool.
8185
/// @param minBucketSize minimum bucket size. Must be power of 2.
8286
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
@@ -85,6 +89,7 @@ umfDisjointPoolParamsSetMinBucketSize(umf_disjoint_pool_params_handle_t hParams,
8589
size_t minBucketSize);
8690

8791
/// @brief Set trace level for pool usage statistics.
92+
/// @details Default value for pool trace is 0 (no traces).
8893
/// @param hParams handle to the parameters of the disjoint pool.
8994
/// @param poolTrace trace level.
9095
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.

src/pool/pool_disjoint.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,9 +1102,9 @@ umfDisjointPoolParamsCreate(umf_disjoint_pool_params_handle_t *hParams) {
11021102
}
11031103

11041104
*params = (umf_disjoint_pool_params_t){
1105-
.slab_min_size = 0,
1106-
.max_poolable_size = 0,
1107-
.capacity = 0,
1105+
.slab_min_size = 64 * 1024, // 64K
1106+
.max_poolable_size = 2 * 1024 * 1024, // 2MB
1107+
.capacity = 4,
11081108
.min_bucket_size = UMF_DISJOINT_POOL_MIN_BUCKET_DEFAULT_SIZE,
11091109
.cur_pool_size = 0,
11101110
.pool_trace = 0,

src/pool/pool_disjoint_internal.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,23 +110,23 @@ typedef struct umf_disjoint_pool_shared_limits_t {
110110

111111
typedef struct umf_disjoint_pool_params_t {
112112
// Minimum allocation size that will be requested from the memory provider.
113-
size_t slab_min_size;
113+
size_t slab_min_size; // Default: 64KB
114114

115115
// Allocations up to this limit will be subject to chunking/pooling
116-
size_t max_poolable_size;
116+
size_t max_poolable_size; // Default: 2MB
117117

118118
// When pooling, each bucket will hold a max of 'capacity' unfreed slabs
119-
size_t capacity;
119+
size_t capacity; // Default: 4
120120

121121
// Holds the minimum bucket size valid for allocation of a memory type.
122122
// This value must be a power of 2.
123-
size_t min_bucket_size;
123+
size_t min_bucket_size; // Default: 8
124124

125125
// Holds size of the pool managed by the allocator.
126-
size_t cur_pool_size;
126+
size_t cur_pool_size; // Default: 0
127127

128128
// Whether to print pool usage statistics
129-
int pool_trace;
129+
int pool_trace; // Default: 0
130130

131131
// Memory limits that can be shared between multiple pool instances,
132132
// i.e. if multiple pools use the same shared_limits sum of those pools'

test/pools/disjoint_pool.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,140 @@ TEST_F(test, disjointPoolName) {
361361
umfDisjointPoolParamsDestroy(params);
362362
}
363363

364+
TEST_F(test, disjointPoolDefaultParams) {
365+
// Disjoint pool defaults
366+
static constexpr size_t DefaultSlabMinSize = 64 * 1024; // 64K
367+
static constexpr size_t DefaultMaxPoolableSize = 2 * 1024 * 1024; // 2MB
368+
369+
umf_disjoint_pool_params_handle_t params = nullptr;
370+
umf_memory_pool_handle_t pool = nullptr;
371+
umf_memory_provider_handle_t provider_handle = nullptr;
372+
373+
// Create disjoint pool parameters with default settings
374+
umf_result_t res = umfDisjointPoolParamsCreate(&params);
375+
EXPECT_EQ(res, UMF_RESULT_SUCCESS);
376+
377+
size_t expected_free_counter = 0;
378+
static size_t free_counter = 0;
379+
static size_t last_requested_size = 0;
380+
struct memory_provider : public umf_test::provider_base_t {
381+
umf_result_t alloc(size_t size, size_t alignment, void **ptr) noexcept {
382+
*ptr = umf_ba_global_aligned_alloc(size, alignment);
383+
last_requested_size = size;
384+
return UMF_RESULT_SUCCESS;
385+
}
386+
387+
umf_result_t free(void *ptr, [[maybe_unused]] size_t size) noexcept {
388+
// do the actual free only when we expect the success
389+
umf_ba_global_free(ptr);
390+
free_counter++;
391+
return UMF_RESULT_SUCCESS;
392+
}
393+
};
394+
395+
umf_memory_provider_ops_t provider_ops =
396+
umf_test::providerMakeCOps<memory_provider, void>();
397+
398+
auto providerUnique =
399+
wrapProviderUnique(createProviderChecked(&provider_ops, nullptr));
400+
provider_handle = providerUnique.get();
401+
402+
res = umfDisjointPoolParamsSetTrace(params, 3);
403+
ASSERT_EQ(res, UMF_RESULT_SUCCESS);
404+
405+
umf_result_t ret = umfPoolCreate(umfDisjointPoolOps(), provider_handle,
406+
params, UMF_POOL_CREATE_FLAG_NONE, &pool);
407+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
408+
409+
// Test allocation and deallocation
410+
// This will use the default disjoint pool parameters
411+
void *ptr = umfPoolMalloc(pool, DefaultSlabMinSize - 1); // Should use pool
412+
ASSERT_NE(ptr, nullptr);
413+
ASSERT_EQ(
414+
last_requested_size,
415+
DefaultSlabMinSize); // First allocated size should be at least the slab min size
416+
ret = umfPoolFree(pool, ptr);
417+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
418+
ASSERT_EQ(free_counter, expected_free_counter);
419+
420+
// Test allocation and deallocation with a different size
421+
expected_free_counter = 1;
422+
ptr =
423+
umfPoolMalloc(pool, DefaultMaxPoolableSize + 1); // Fallback to provider
424+
ASSERT_EQ(last_requested_size, DefaultMaxPoolableSize + 1);
425+
ASSERT_NE(ptr, nullptr);
426+
ret = umfPoolFree(pool, ptr);
427+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
428+
ASSERT_EQ(free_counter, expected_free_counter);
429+
430+
// Cleaning up
431+
umfPoolDestroy(pool);
432+
umfDisjointPoolParamsDestroy(params);
433+
expected_free_counter = 2;
434+
ASSERT_EQ(free_counter, expected_free_counter);
435+
}
436+
437+
TEST_F(test, disjointPoolDefaultCapacity) {
438+
// Disjoint pool defaults
439+
static constexpr size_t DefaultSlabMinSize = 64 * 1024; // 64K
440+
static constexpr size_t DefaultCapacity = 4;
441+
442+
static size_t free_counter = 0;
443+
static size_t last_requested_size = 0;
444+
445+
struct memory_provider : public umf_test::provider_base_t {
446+
umf_result_t alloc(size_t size, size_t alignment, void **ptr) noexcept {
447+
*ptr = umf_ba_global_aligned_alloc(size, alignment);
448+
last_requested_size = size;
449+
return UMF_RESULT_SUCCESS;
450+
}
451+
umf_result_t free(void *ptr, [[maybe_unused]] size_t size) noexcept {
452+
// do the actual free only when we expect the success
453+
umf_ba_global_free(ptr);
454+
free_counter++;
455+
return UMF_RESULT_SUCCESS;
456+
}
457+
};
458+
umf_memory_provider_ops_t provider_ops =
459+
umf_test::providerMakeCOps<memory_provider, void>();
460+
auto providerUnique =
461+
wrapProviderUnique(createProviderChecked(&provider_ops, nullptr));
462+
umf_memory_provider_handle_t provider_handle = providerUnique.get();
463+
umf_disjoint_pool_params_handle_t params = nullptr;
464+
umf_result_t ret = umfDisjointPoolParamsCreate(&params);
465+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
466+
467+
umf_memory_pool_handle_t pool = nullptr;
468+
ret = umfPoolCreate(umfDisjointPoolOps(), provider_handle, params,
469+
UMF_POOL_CREATE_FLAG_NONE, &pool);
470+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
471+
472+
// Test capacity
473+
void *ptrs[DefaultCapacity + 1];
474+
for (size_t i = 0; i < DefaultCapacity + 1; ++i) {
475+
ptrs[i] =
476+
umfPoolMalloc(pool, DefaultSlabMinSize - 1); // Should use pool
477+
ASSERT_NE(ptrs[i], nullptr);
478+
ASSERT_EQ(last_requested_size, DefaultSlabMinSize);
479+
}
480+
481+
size_t i;
482+
for (i = 0; i < DefaultCapacity + 1; ++i) {
483+
ret = umfPoolFree(pool, ptrs[i]);
484+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
485+
}
486+
ASSERT_EQ(
487+
free_counter,
488+
i - DefaultCapacity); // only the last allocation exceeds the capacity
489+
490+
// Cleaning up
491+
umfPoolDestroy(pool);
492+
umfDisjointPoolParamsDestroy(params);
493+
ASSERT_EQ(free_counter,
494+
DefaultCapacity +
495+
1); // +1 for the last allocation that exceeded the capacity
496+
}
497+
364498
INSTANTIATE_TEST_SUITE_P(disjointPoolTests, umfPoolTest,
365499
::testing::Values(poolCreateExtParams{
366500
umfDisjointPoolOps(), defaultDisjointPoolConfig,

0 commit comments

Comments
 (0)