8000 Re-bin segment when memory pages are freed. · postgres/postgres@1605623 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1605623

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 13f1278 commit 1605623

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);
@@ -1848,6 +1853,11 @@ destroy_superblock(dsa_area *area, dsa_pointer span_pointer)
18481853
segment_map->mapped_address = NULL;
18491854
}
18501855
}
1856+
1857+
/* Move segment to appropriate bin if necessary. */
1858+
if (segment_map->header != NULL)
1859+
rebin_segment(area, segment_map);
1860+
18511861
LWLockRelease(DSA_AREA_LOCK(area));
18521862

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

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

0 commit comments

Comments
 (0)
0