diff --git a/src/box/tuple.cc b/src/box/tuple.cc index c21a02f1218ba233179394e0091ff1774d320899..ed71c2108350544f62642c8b9bed19f214ac969a 100644 --- a/src/box/tuple.cc +++ b/src/box/tuple.cc @@ -539,17 +539,15 @@ tuple_init(float arena_prealloc, uint32_t objsize_min, } else { flags = MAP_SHARED; } - size_t slab_size = 4*1024*1024; + uint32_t slab_size = 4*1024*1024; size_t prealloc = arena_prealloc * 1024 * 1024 * 1024; - slab_arena_create(&tuple_arena, slab_size, - prealloc, prealloc, flags); + slab_arena_create(&tuple_arena, prealloc, prealloc, + slab_size, flags); slab_cache_create(&tuple_slab_cache, &tuple_arena, slab_size); small_alloc_create(&talloc, &tuple_slab_cache, - objsize_min, - (slab_size - mslab_sizeof())/4, - alloc_factor); + objsize_min, alloc_factor); } void diff --git a/src/lib/small/mempool.h b/src/lib/small/mempool.h index b21aef58798ca1074268704b7ae8f9a8e6239679..e54e720f5ce95b361722aae263b780ba6e15d481 100644 --- a/src/lib/small/mempool.h +++ b/src/lib/small/mempool.h @@ -118,6 +118,18 @@ mslab_sizeof() return small_align(sizeof(struct mslab), sizeof(intptr_t)); } +/** + * Calculate the maximal size of an object for which it makes + * sense to create a memory pool given the size of the slab. + */ +static inline uint32_t +mempool_objsize_max(uint32_t slab_size) +{ + /* Fit at least 4 objects in a slab, aligned by pointer size. */ + return ((slab_size - mslab_sizeof() - MEMPOOL_MAP_SIZEOF)/4) & + ~(sizeof(intptr_t) - 1); +} + typedef rb_tree(struct mslab) mslab_tree_t; /** A memory pool. */ diff --git a/src/lib/small/small.c b/src/lib/small/small.c index f28cb098c3dfe5d54292eb0a541adc16927714a1..8bc3ca9253f9e59f173f212e2b40c88be227de82 100644 --- a/src/lib/small/small.c +++ b/src/lib/small/small.c @@ -61,6 +61,7 @@ factor_pool_create(struct small_alloc *alloc, size_t size) { assert(size > alloc->step_pool_objsize_max); + assert(size <= alloc->objsize_max); if (alloc->factor_pool_next == NULL) { /** @@ -82,6 +83,8 @@ factor_pool_create(struct small_alloc *alloc, sizeof(intptr_t)); assert(objsize > alloc->step_pool_objsize_max); } while (objsize < size); + if (objsize > alloc->objsize_max) + objsize = alloc->objsize_max; struct factor_pool *pool = alloc->factor_pool_next; alloc->factor_pool_next= pool->next; mempool_create_with_order(&pool->pool, alloc->cache, @@ -94,21 +97,16 @@ factor_pool_create(struct small_alloc *alloc, /** Initialize the small allocator. */ void small_alloc_create(struct small_alloc *alloc, struct slab_cache *cache, - uint32_t objsize_min, uint32_t objsize_max, - float alloc_factor) + uint32_t objsize_min, float alloc_factor) { alloc->cache = cache; /* Align sizes. */ objsize_min = small_align(objsize_min, sizeof(intptr_t)); - objsize_max = small_align(objsize_max, sizeof(intptr_t)); - assert(objsize_max > objsize_min + STEP_POOL_MAX * STEP_SIZE); - /* - * Make sure at least 4 largest objects can fit in a slab. - * This asserts if objsize_max is too large to fit in an - * ordered slab nicely. - */ - alloc->slab_order = slab_order(alloc->cache, - objsize_max * 4 + mslab_sizeof()); + alloc->slab_order = cache->order_max; + /* Make sure at least 4 largest objects can fit in a slab. */ + alloc->objsize_max = + mempool_objsize_max(slab_order_size(cache, alloc->slab_order)); + assert(alloc->objsize_max > objsize_min + STEP_POOL_MAX * STEP_SIZE); struct mempool *step_pool; for (step_pool = alloc->step_pools; @@ -145,7 +143,7 @@ small_alloc_create(struct small_alloc *alloc, struct slab_cache *cache, factor_pool->next = NULL; alloc->factor_pool_next = alloc->factor_pool_cache; factor_tree_new(&alloc->factor_pools); - (void) factor_pool_create(alloc, NULL, objsize_max); + (void) factor_pool_create(alloc, NULL, alloc->objsize_max); alloc->is_delayed_free_mode = false; } diff --git a/src/lib/small/small.h b/src/lib/small/small.h index 2ae8a9029ff43366c1cc5984b06c4e41bcf24221..6d77797b228aa7bf3a89dd8205cddd17a97da378 100644 --- a/src/lib/small/small.h +++ b/src/lib/small/small.h @@ -153,6 +153,7 @@ struct small_alloc { * Is provided during initialization. */ float factor; + uint32_t objsize_max; /** All slabs in all mempools have the same order. */ uint8_t slab_order; /** @@ -164,8 +165,7 @@ struct small_alloc { /** Initialize a small memory allocator. */ void small_alloc_create(struct small_alloc *alloc, struct slab_cache *cache, - uint32_t objsize_min, uint32_t objsize_max, - float alloc_factor); + uint32_t objsize_min, float alloc_factor); /** * Enter or leave delayed mode - in delayed mode smfree_delayed() diff --git a/test/unit/small_alloc.c b/test/unit/small_alloc.c index d411253bc2ec39bc3daf53caa0a069d3c37a68f0..85bec1474a41e8784dc90e50fa346e2def05abd2 100644 --- a/test/unit/small_alloc.c +++ b/test/unit/small_alloc.c @@ -74,8 +74,7 @@ small_alloc_basic() int i; header(); - small_alloc_create(&alloc, &cache, OBJSIZE_MIN, OBJSIZE_MAX, - 1.3); + small_alloc_create(&alloc, &cache, OBJSIZE_MIN, 1.3); for (i = 0; i < ITERATIONS_MAX; i++) { basic_alloc_streak(); diff --git a/test/wal/oom.result b/test/wal/oom.result index 352277546abfa365173dcdf9a374036e668f7142..cd5c5336fe7da26921a6c2223bcef13336ff11cf 100644 --- a/test/wal/oom.result +++ b/test/wal/oom.result @@ -15,11 +15,11 @@ while true do i = i + 1 end; --- -- error: Failed to allocate 188 bytes in slab allocator for tuple +- error: Failed to allocate 313 bytes in slab allocator for tuple ... space:len(); --- -- 42 +- 73 ... i = 1; --- @@ -29,11 +29,11 @@ while true do i = i + 1 end; --- -- error: Failed to allocate 188 bytes in slab allocator for tuple +- error: Failed to allocate 314 bytes in slab allocator for tuple ... space:len(); --- -- 84 +- 146 ... i = 1; --- @@ -43,12 +43,12 @@ while true do i = i + 1 end; --- -- error: Failed to allocate 188 bytes in slab allocator for tuple +- error: Failed to allocate 314 bytes in slab allocator for tuple ... --# setopt delimiter '' space:len() --- -- 126 +- 219 ... space.index['primary']:select(0) --- @@ -132,14 +132,14 @@ t - [39, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] - [40, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] - [41, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] - - [42, 'test'] - - [43, 'testtest'] - - [44, 'testtesttest'] - - [45, 'testtesttesttest'] - - [46, 'testtesttesttesttest'] - - [47, 'testtesttesttesttesttest'] - - [48, 'testtesttesttesttesttesttest'] - - [49, 'testtesttesttesttesttesttesttest'] + - [42, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] + - [43, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] + - [44, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] + - [45, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] + - [46, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] + - [47, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] + - [48, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] + - [49, 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest'] ... space:truncate() ---