Optimize extent coalescing.

Refactor extent_can_coalesce(), extent_coalesce(), and extent_record()
to avoid needlessly repeating extent [de]activation operations.
This commit is contained in:
Jason Evans 2017-02-12 23:00:19 -08:00
parent b0654b95ed
commit c1ebfaa673

View File

@ -1020,14 +1020,19 @@ extent_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,
} }
static bool static bool
extent_can_coalesce(const extent_t *a, const extent_t *b) { extent_can_coalesce(arena_t *arena, extents_t *extents, const extent_t *inner,
if (extent_arena_get(a) != extent_arena_get(b)) { const extent_t *outer) {
assert(extent_arena_get(inner) == arena);
if (extent_arena_get(outer) != arena) {
return false; return false;
} }
if (extent_state_get(a) != extent_state_get(b)) {
assert(extent_state_get(inner) == extent_state_active);
if (extent_state_get(outer) != extents->state) {
return false; return false;
} }
if (extent_committed_get(a) != extent_committed_get(b)) {
if (extent_committed_get(inner) != extent_committed_get(outer)) {
return false; return false;
} }
@ -1036,24 +1041,21 @@ extent_can_coalesce(const extent_t *a, const extent_t *b) {
static bool static bool
extent_coalesce(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, extent_coalesce(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
extent_t *a, extent_t *b, extents_t *extents) { extents_t *extents, extent_t *inner, extent_t *outer, bool forward) {
assert(extent_can_coalesce(a, b)); assert(extent_can_coalesce(arena, extents, inner, outer));
assert(extent_arena_get(a) == arena);
assert(extent_arena_get(b) == arena);
extent_activate_locked(tsdn, arena, extents, a); extent_activate_locked(tsdn, arena, extents, outer);
extent_activate_locked(tsdn, arena, extents, b);
malloc_mutex_unlock(tsdn, &extents->mtx); malloc_mutex_unlock(tsdn, &extents->mtx);
bool err = extent_merge_wrapper(tsdn, arena, r_extent_hooks, a, b); bool err = extent_merge_wrapper(tsdn, arena, r_extent_hooks,
forward ? inner : outer, forward ? outer : inner);
malloc_mutex_lock(tsdn, &extents->mtx); malloc_mutex_lock(tsdn, &extents->mtx);
extent_deactivate_locked(tsdn, arena, extents, a);
if (err) { if (err) {
extent_deactivate_locked(tsdn, arena, extents, b); extent_deactivate_locked(tsdn, arena, extents, outer);
return true;
} }
return false; return err;
} }
static void static void
@ -1075,7 +1077,6 @@ extent_record(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
} }
assert(extent_lookup(tsdn, extent_base_get(extent), true) == extent); assert(extent_lookup(tsdn, extent_base_get(extent), true) == extent);
extent_deactivate_locked(tsdn, arena, extents, extent);
/* /*
* Continue attempting to coalesce until failure, to protect against * Continue attempting to coalesce until failure, to protect against
@ -1098,10 +1099,10 @@ extent_record(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
* before releasing the next_elm lock. * before releasing the next_elm lock.
*/ */
bool can_coalesce = (next != NULL && bool can_coalesce = (next != NULL &&
extent_can_coalesce(extent, next)); extent_can_coalesce(arena, extents, extent, next));
rtree_elm_release(tsdn, &extents_rtree, next_elm); rtree_elm_release(tsdn, &extents_rtree, next_elm);
if (can_coalesce && !extent_coalesce(tsdn, arena, if (can_coalesce && !extent_coalesce(tsdn, arena,
r_extent_hooks, extent, next, extents)) { r_extent_hooks, extents, extent, next, true)) {
coalesced = true; coalesced = true;
} }
} }
@ -1114,16 +1115,18 @@ extent_record(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks,
extent_t *prev = rtree_elm_read_acquired(tsdn, extent_t *prev = rtree_elm_read_acquired(tsdn,
&extents_rtree, prev_elm); &extents_rtree, prev_elm);
bool can_coalesce = (prev != NULL && bool can_coalesce = (prev != NULL &&
extent_can_coalesce(prev, extent)); extent_can_coalesce(arena, extents, extent, prev));
rtree_elm_release(tsdn, &extents_rtree, prev_elm); rtree_elm_release(tsdn, &extents_rtree, prev_elm);
if (can_coalesce && !extent_coalesce(tsdn, arena, if (can_coalesce && !extent_coalesce(tsdn, arena,
r_extent_hooks, prev, extent, extents)) { r_extent_hooks, extents, extent, prev, false)) {
extent = prev; extent = prev;
coalesced = true; coalesced = true;
} }
} }
} while (coalesced); } while (coalesced);
extent_deactivate_locked(tsdn, arena, extents, extent);
malloc_mutex_unlock(tsdn, &extents->mtx); malloc_mutex_unlock(tsdn, &extents->mtx);
} }