Skip to content

Commit 74ad9b0

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 255a925 commit 74ad9b0

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
@@ -406,6 +406,7 @@ static dsa_area *attach_internal(void *place, dsm_segment *segment,
406406
dsa_handle handle);
407407
static void check_for_freed_segments(dsa_area *area);
408408
static void check_for_freed_segments_locked(dsa_area *area);
409+
static void rebin_segment(dsa_area *area, dsa_segment_map *segment_map);
409410

410411
/*
411412
* Create a new shared area in a new DSM segment. Further DSM segments will
@@ -857,7 +858,11 @@ dsa_free(dsa_area *area, dsa_pointer dp)
857858
FreePageManagerPut(segment_map->fpm,
858859
DSA_EXTRACT_OFFSET(span->start) / FPM_PAGE_SIZE,
859860
span->npages);
861+
862+
/* Move segment to appropriate bin if necessary. */
863+
rebin_segment(area, segment_map);
860864
LWLockRelease(DSA_AREA_LOCK(area));
865+
861866
/* Unlink span. */
862867
LWLockAcquire(DSA_SCLASS_LOCK(area, DSA_SCLASS_SPAN_LARGE),
863868
LW_EXCLUSIVE);
@@ -1849,6 +1854,11 @@ destroy_superblock(dsa_area *area, dsa_pointer span_pointer)
18491854
segment_map->mapped_address = NULL;
18501855
}
18511856
}
1857+
1858+
/* Move segment to appropriate bin if necessary. */
1859+
if (segment_map->header != NULL)
1860+
rebin_segment(area, segment_map);
1861+
18521862
LWLockRelease(DSA_AREA_LOCK(area));
18531863

18541864
/*
@@ -2012,28 +2022,7 @@ get_best_segment(dsa_area *area, size_t npages)
20122022
/* Re-bin it if it's no longer in the appropriate bin. */
20132023
if (contiguous_pages < threshold)
20142024
{
2015-
size_t new_bin;
2016-
2017-
new_bin = contiguous_pages_to_segment_bin(contiguous_pages);
2018-
2019-
/* Remove it from its current bin. */
2020-
unlink_segment(area, segment_map);
2021-
2022-
/* Push it onto the front of its new bin. */
2023-
segment_map->header->prev = DSA_SEGMENT_INDEX_NONE;
2024-
segment_map->header->next =
2025-
area->control->segment_bins[new_bin];
2026-
segment_map->header->bin = new_bin;
2027-
area->control->segment_bins[new_bin] = segment_index;
2028-
if (segment_map->header->next != DSA_SEGMENT_INDEX_NONE)
2029-
{
2030-
dsa_segment_map *next;
2031-
2032-
next = get_segment_by_index(area,
2033-
segment_map->header->next);
2034-
Assert(next->header->bin == new_bin);
2035-
next->header->prev = segment_index;
2036-
}
2025+
rebin_segment(area, segment_map);
20372026

20382027
/*
20392028
* But fall through to see if it's enough to satisfy this
@@ -2288,3 +2277,35 @@ check_for_freed_segments_locked(dsa_area *area)
22882277
area->freed_segment_counter = freed_segment_counter;
22892278
}
22902279
}
2280+
2281+
/*
2282+
* Re-bin segment if it's no longer in the appropriate bin.
2283+
*/
2284+
static void
2285+
rebin_segment(dsa_area *area, dsa_segment_map *segment_map)
2286+
{
2287+
size_t new_bin;
2288+
dsa_segment_index segment_index;
2289+
2290+
new_bin = contiguous_pages_to_segment_bin(fpm_largest(segment_map->fpm));
2291+
if (segment_map->header->bin == new_bin)
2292+
return;
2293+
2294+
/* Remove it from its current bin. */
2295+
unlink_segment(area, segment_map);
2296+
2297+
/* Push it onto the front of its new bin. */
2298+
segment_index = get_segment_index(area, segment_map);
2299+
segment_map->header->prev = DSA_SEGMENT_INDEX_NONE;
2300+
segment_map->header->next = area->control->segment_bins[new_bin];
2301+
segment_map->header->bin = new_bin;
2302+
area->control->segment_bins[new_bin] = segment_index;
2303+
if (segment_map->header->next != DSA_SEGMENT_INDEX_NONE)
2304+
{
2305+
dsa_segment_map *next;
2306+
2307+
next = get_segment_by_index(area, segment_map->header->next);
2308+
Assert(next->header->bin == new_bin);
2309+
next->header->prev = segment_index;
2310+
}
2311+
}

0 commit comments

Comments
 (0)