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.
This commit is contained in:
Jason Evans 2017-03-22 20:06:25 -07:00
parent bbc16a50f9
commit a832ebaee9

View File

@ -256,21 +256,13 @@ extents_remove_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent,
cur_extents_npages - (size >> LG_PAGE), ATOMIC_RELAXED); cur_extents_npages - (size >> LG_PAGE), ATOMIC_RELAXED);
} }
/* /* Do any-best-fit extent selection, i.e. select any extent that best fits. */
* 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}.
*/
static extent_t * static extent_t *
extents_best_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, extents_best_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents,
size_t size) { size_t size) {
malloc_mutex_assert_owner(tsdn, &extents->mtx);
pszind_t pind = psz2ind(extent_size_quantize_ceil(size)); pszind_t pind = psz2ind(extent_size_quantize_ceil(size));
for (pszind_t i = pind; i < NPSIZES+1; i++) { for (pszind_t i = pind; i < NPSIZES+1; i++) {
extent_t *extent = extents->delay_coalesce ? extent_t *extent = extent_heap_any(&extents->heaps[i]);
extent_heap_any(&extents->heaps[i]) :
extent_heap_first(&extents->heaps[i]);
if (extent != NULL) { if (extent != NULL) {
assert(extent_size_get(extent) >= size); assert(extent_size_get(extent) >= size);
return extent; return extent;
@ -280,6 +272,45 @@ extents_best_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents,
return NULL; 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 static bool
extent_try_delayed_coalesce(tsdn_t *tsdn, arena_t *arena, extent_try_delayed_coalesce(tsdn_t *tsdn, arena_t *arena,
extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, 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; extent = NULL;
} }
} else { } else {
extent = extents_best_fit_locked(tsdn, arena, extents, extent = extents_fit_locked(tsdn, arena, extents, alloc_size);
alloc_size);
} }
if (extent == NULL) { if (extent == NULL) {
if (!locked) { if (!locked) {