From a832ebaee905522fafa1be438dbf3fb5066f1e00 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Wed, 22 Mar 2017 20:06:25 -0700 Subject: [PATCH] Use first fit layout policy instead of best fit. For extents which do not delay coalescing, use first fit layout policy rather than first-best fit layout policy. This packs extents toward older virtual memory mappings, but at the cost of higher search overhead in the common case. This resolves #711. --- src/extent.c | 54 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/extent.c b/src/extent.c index f1b513e4..f04fd01a 100644 --- a/src/extent.c +++ b/src/extent.c @@ -256,21 +256,13 @@ extents_remove_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, cur_extents_npages - (size >> LG_PAGE), ATOMIC_RELAXED); } -/* - * Do {first,any}-best-fit extent selection, i.e. select the oldest/lowest or - * any extent that best fits, where {first,any} corresponds to - * extents->delay_coalesce={false,true}. - */ +/* Do any-best-fit extent selection, i.e. select any extent that best fits. */ static extent_t * extents_best_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, size_t size) { - malloc_mutex_assert_owner(tsdn, &extents->mtx); - pszind_t pind = psz2ind(extent_size_quantize_ceil(size)); for (pszind_t i = pind; i < NPSIZES+1; i++) { - extent_t *extent = extents->delay_coalesce ? - extent_heap_any(&extents->heaps[i]) : - extent_heap_first(&extents->heaps[i]); + extent_t *extent = extent_heap_any(&extents->heaps[i]); if (extent != NULL) { assert(extent_size_get(extent) >= size); return extent; @@ -280,6 +272,45 @@ extents_best_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, return NULL; } +/* + * Do first-fit extent selection, i.e. select the oldest/lowest extent that is + * large enough. + */ +static extent_t * +extents_first_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, + size_t size) { + extent_t *ret = NULL; + + pszind_t pind = psz2ind(extent_size_quantize_ceil(size)); + for (pszind_t i = pind; i < NPSIZES+1; i++) { + extent_t *extent = extent_heap_first(&extents->heaps[i]); + if (extent != NULL) { + assert(extent_size_get(extent) >= size); + if (ret == NULL || extent_snad_comp(extent, ret) < 0) { + ret = extent; + } + } + } + + return ret; +} + +/* + * Do {best,first}-fit extent selection, where the selection policy choice is + * based on extents->delay_coalesce. Best-fit selection requires less + * searching, but its layout policy is less stable and may cause higher virtual + * memory fragmentation as a side effect. + */ +static extent_t * +extents_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, + size_t size) { + malloc_mutex_assert_owner(tsdn, &extents->mtx); + + return extents->delay_coalesce ? extents_best_fit_locked(tsdn, arena, + extents, size) : extents_first_fit_locked(tsdn, arena, extents, + size); +} + static bool extent_try_delayed_coalesce(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, @@ -675,8 +706,7 @@ extent_recycle_extract(tsdn_t *tsdn, arena_t *arena, extent = NULL; } } else { - extent = extents_best_fit_locked(tsdn, arena, extents, - alloc_size); + extent = extents_fit_locked(tsdn, arena, extents, alloc_size); } if (extent == NULL) { if (!locked) {