Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 03f80da

Browse files
committed
Re-bin segment when memory pages are freed.
It's OK to be lazy about re-binning memory segments when allocating, because that can only leave segments in a bin that's too high. We'll search higher bins if necessary while allocating next time, and also eventually re-bin, so no memory can become unreachable that way. However, when freeing memory, the largest contiguous range of free pages might go up, so we should re-bin eagerly to make sure we don't leave the segment in a bin that is too low for get_best_segment() to find. The re-binning code is moved into a function of its own, so it can be called whenever free pages are returned to the segment's free page map. Back-patch to all supported releases. Author: Dongming Liu <ldming101@gmail.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> (earlier version) Reviewed-by: Thomas Munro <thomas.munro@gmail.com> Discussion: https://postgr.es/m/CAL1p7e8LzB2LSeAXo2pXCW4%2BRya9s0sJ3G_ReKOU%3DAjSUWjHWQ%40mail.gmail.com
1 parent a8c09da commit 03f80da

File tree

1 file changed

+43
-22
lines changed
  • src/backend/utils/mmgr

1 file changed

+43
-22
lines changed

src/backend/utils/mmgr/dsa.c

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ static dsa_area *attach_internal(void *place, dsm_segment *segment,
418418
dsa_handle handle);
419419
static void check_for_freed_segments(dsa_area *area);
420420
static void check_for_freed_segments_locked(dsa_area *area);
421+
static void rebin_segment(dsa_area *area, dsa_segment_map *segment_map);
421422

422423
/*
423424
* Create a new shared area in a new DSM segment. Further DSM segments will
@@ -869,7 +870,11 @@ dsa_free(dsa_area *area, dsa_pointer dp)
869870
FreePageManagerPut(segment_map->fpm,
870871
DSA_EXTRACT_OFFSET(span->start) / FPM_PAGE_SIZE,
871872
span->npages);
873+
874+
/* Move segment to appropriate bin if necessary. */
875+
rebin_segment(area, segment_map);
872876
LWLockRelease(DSA_AREA_LOCK(area));
877+
873878
/* Unlink span. */
874879
LWLockAcquire(DSA_SCLASS_LOCK(area, DSA_SCLASS_SPAN_LARGE),
875880
LW_EXCLUSIVE);
@@ -1858,6 +1863,11 @@ destroy_superblock(dsa_area *area, dsa_pointer span_pointer)
18581863
segment_map->mapped_address = NULL;
18591864
}
18601865
}
1866+
1867+
/* Move segment to appropriate bin if necessary. */
1868+
if (segment_map->header != NULL)
1869+
rebin_segment(area, segment_map);
1870+
18611871
LWLockRelease(DSA_AREA_LOCK(area));
18621872

18631873
/*
@@ -2021,28 +2031,7 @@ get_best_segment(dsa_area *area, size_t npages)
20212031
/* Re-bin it if it's no longer in the appropriate bin. */
20222032
if (contiguous_pages < threshold)
20232033
{
2024-
size_t new_bin;
2025-
2026-
new_bin = contiguous_pages_to_segment_bin(contiguous_pages);
2027-
2028-
/* Remove it from its current bin. */
2029-
unlink_segment(area, segment_map);
2030-
2031-
/* Push it onto the front of its new bin. */
2032-
segment_map->header->prev = DSA_SEGMENT_INDEX_NONE;
2033-
segment_map->header->next =
2034-
area->control->segment_bins[new_bin];
2035-
segment_map->header->bin = new_bin;
2036-
area->control->segment_bins[new_bin] = segment_index;
2037-
if (segment_map->header->next != DSA_SEGMENT_INDEX_NONE)
2038-
{
2039-
dsa_segment_map *next;
2040-
2041-
next = get_segment_by_index(area,
2042-
segment_map->header->next);
2043-
Assert(next->header->bin == new_bin);
2044-
next->header->prev = segment_index;
2045-
}
2034+
rebin_segment(area, segment_map);
20462035

20472036
/*
20482037
* But fall through to see if it's enough to satisfy this
@@ -2297,3 +2286,35 @@ check_for_freed_segments_locked(dsa_area *area)
22972286
area->freed_segment_counter = freed_segment_counter;
22982287
}
22992288
}
2289+
2290+
/*
2291+
* Re-bin segment if it's no longer in the appropriate bin.
2292+
*/
2293+
static void
2294+
rebin_segment(dsa_area *area, dsa_segment_map *segment_map)
2295+
{
2296+
size_t new_bin;
2297+
dsa_segment_index segment_index;
2298+
2299+
new_bin = contiguous_pages_to_segment_bin(fpm_largest(segment_map->fpm));
2300+
if (segment_map->header->bin == new_bin)
2301+
return;
2302+
2303+
/* Remove it from its current bin. */
2304+
unlink_segment(area, segment_map);
2305+
2306+
/* Push it onto the front of its new bin. */
2307+
segment_index = get_segment_index(area, segment_map);
2308+
segment_map->header->prev = DSA_SEGMENT_INDEX_NONE;
2309+
segment_map->header->next = area->control->segment_bins[new_bin];
2310+
segment_map->header->bin = new_bin;
2311+
area->control->segment_bins[new_bin] = segment_index;
2312+
if (segment_map->header->next != DSA_SEGMENT_INDEX_NONE)
2313+
{
2314+
dsa_segment_map *next;
2315+
2316+
next = get_segment_by_index(area, segment_map->header->next);
2317+
Assert(next->header->bin == new_bin);
2318+
next->header->prev = segment_index;
2319+
}
2320+
}

0 commit comments

Comments
 (0)