Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bb952c8

Browse files
Allow specifying initial and maximum segment sizes for DSA.
Previously, the DSA segment size always started with 1MB and grew up to DSA_MAX_SEGMENT_SIZE. It was inconvenient in certain scenarios, such as when the caller desired a soft constraint on the total DSA segment size, limiting it to less than 1MB. This commit introduces the capability to specify the initial and maximum DSA segment sizes when creating a DSA area, providing more flexibility and control over memory usage. Reviewed-by: John Naylor, Tomas Vondra Discussion: https://postgr.es/m/CAD21AoAYGGC1ePjVX0H%2Bpp9rH%3D9vuPK19nNOiu12NprdV5TVJA%40mail.gmail.com
1 parent 1f42337 commit bb952c8

File tree

2 files changed

+71
-38
lines changed

2 files changed

+71
-38
lines changed

src/backend/utils/mmgr/dsa.c

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,6 @@
5959
#include "utils/memutils.h"
6060
#include "utils/resowner.h"
6161

62-
/*
63-
* The size of the initial DSM segment that backs a dsa_area created by
64-
* dsa_create. After creating some number of segments of this size we'll
65-
* double this size, and so on. Larger segments may be created if necessary
66-
* to satisfy large requests.
67-
*/
68-
#define DSA_INITIAL_SEGMENT_SIZE ((size_t) (1 * 1024 * 1024))
69-
7062
/*
7163
* How many segments to create before we double the segment size. If this is
7264
* low, then there is likely to be a lot of wasted space in the largest
@@ -76,17 +68,6 @@
7668
*/
7769
#define DSA_NUM_SEGMENTS_AT_EACH_SIZE 2
7870

79-
/*
80-
* The number of bits used to represent the offset part of a dsa_pointer.
81-
* This controls the maximum size of a segment, the maximum possible
82-
* allocation size and also the maximum number of segments per area.
83-
*/
84-
#if SIZEOF_DSA_POINTER == 4
85-
#define DSA_OFFSET_WIDTH 27 /* 32 segments of size up to 128MB */
86-
#else
87-
#define DSA_OFFSET_WIDTH 40 /* 1024 segments of size up to 1TB */
88-
#endif
89-
9071
/*
9172
* The maximum number of DSM segments that an area can own, determined by
9273
* the number of bits remaining (but capped at 1024).
@@ -97,9 +78,6 @@
9778
/* The bitmask for extracting the offset from a dsa_pointer. */
9879
#define DSA_OFFSET_BITMASK (((dsa_pointer) 1 << DSA_OFFSET_WIDTH) - 1)
9980

100-
/* The maximum size of a DSM segment. */
101-
#define DSA_MAX_SEGMENT_SIZE ((size_t) 1 << DSA_OFFSET_WIDTH)
102-
10381
/* Number of pages (see FPM_PAGE_SIZE) per regular superblock. */
10482
#define DSA_PAGES_PER_SUPERBLOCK 16
10583

@@ -318,6 +296,10 @@ typedef struct
318296
dsa_segment_index segment_bins[DSA_NUM_SEGMENT_BINS];
319297
/* The object pools for each size class. */
320298
dsa_area_pool pools[DSA_NUM_SIZE_CLASSES];
299+
/* initial allocation segment size */
300+
size_t init_segment_size;
301+
/* maximum allocation segment size */
302+
size_t max_segment_size;
321303
/* The total size of all active segments. */
322304
size_t total_segment_size;
323305
/* The maximum total size of backing storage we are allowed. */
@@ -417,7 +399,9 @@ static dsa_segment_map *make_new_segment(dsa_area *area, size_t requested_pages)
417399
static dsa_area *create_internal(void *place, size_t size,
418400
int tranche_id,
419401
dsm_handle control_handle,
420-
dsm_segment *control_segment);
402+
dsm_segment *control_segment,
403+
size_t init_segment_size,
404+
size_t max_segment_size);
421405
static dsa_area *attach_internal(void *place, dsm_segment *segment,
422406
dsa_handle handle);
423407
static void check_for_freed_segments(dsa_area *area);
@@ -434,7 +418,7 @@ static void rebin_segment(dsa_area *area, dsa_segment_map *segment_map);
434418
* we require the caller to provide one.
435419
*/
436420
dsa_area *
437-
dsa_create(int tranche_id)
421+
dsa_create_ext(int tranche_id, size_t init_segment_size, size_t max_segment_size)
438422
{
439423
dsm_segment *segment;
440424
dsa_area *area;
@@ -443,7 +427,7 @@ dsa_create(int tranche_id)
443427
* Create the DSM segment that will hold the shared control object and the
444428
* first segment of usable space.
445429
*/
446-
segment = dsm_create(DSA_INITIAL_SEGMENT_SIZE, 0);
430+
segment = dsm_create(init_segment_size, 0);
447431

448432
/*
449433
* All segments backing this area are pinned, so that DSA can explicitly
@@ -455,9 +439,10 @@ dsa_create(int tranche_id)
455439

456440
/* Create a new DSA area with the control object in this segment. */
457441
area = create_internal(dsm_segment_address(segment),
458-
DSA_INITIAL_SEGMENT_SIZE,
442+
init_segment_size,
459443
tranche_id,
460-
dsm_segment_handle(segment), segment);
444+
dsm_segment_handle(segment), segment,
445+
init_segment_size, max_segment_size);
461446

462447
/* Clean up when the control segment detaches. */
463448
on_dsm_detach(segment, &dsa_on_dsm_detach_release_in_place,
@@ -483,13 +468,15 @@ dsa_create(int tranche_id)
483468
* See dsa_create() for a note about the tranche arguments.
484469
*/
485470
dsa_area *
486-
dsa_create_in_place(void *place, size_t size,
487-
int tranche_id, dsm_segment *segment)
471+
dsa_create_in_place_ext(void *place, size_t size,
472+
int tranche_id, dsm_segment *segment,
473+
size_t init_segment_size, size_t max_segment_size)
488474
{
489475
dsa_area *area;
490476

491477
area = create_internal(place, size, tranche_id,
492-
DSM_HANDLE_INVALID, NULL);
478+
DSM_HANDLE_INVALID, NULL,
479+
init_segment_size, max_segment_size);
493480

494481
/*
495482
* Clean up when the control segment detaches, if a containing DSM segment
@@ -1231,7 +1218,8 @@ static dsa_area *
12311218
create_internal(void *place, size_t size,
12321219
int tranche_id,
12331220
dsm_handle control_handle,
1234-
dsm_segment *control_segment)
1221+
dsm_segment *control_segment,
1222+
size_t init_segment_size, size_t max_segment_size)
12351223
{
12361224
dsa_area_control *control;
12371225
dsa_area *area;
@@ -1241,6 +1229,11 @@ create_internal(void *place, size_t size,
12411229
size_t metadata_bytes;
12421230
int i;
12431231

1232+
/* Check the initial and maximum block sizes */
1233+
Assert(init_segment_size >= DSA_MIN_SEGMENT_SIZE);
1234+
Assert(max_segment_size >= init_segment_size);
1235+
Assert(max_segment_size <= DSA_MAX_SEGMENT_SIZE);
1236+
12441237
/* Sanity check on the space we have to work in. */
12451238
if (size < dsa_minimum_size())
12461239
elog(ERROR, "dsa_area space must be at least %zu, but %zu provided",
@@ -1270,8 +1263,10 @@ create_internal(void *place, size_t size,
12701263
control->segment_header.prev = DSA_SEGMENT_INDEX_NONE;
12711264
control->segment_header.usable_pages = usable_pages;
12721265
control->segment_header.freed = false;
1273-
control->segment_header.size = DSA_INITIAL_SEGMENT_SIZE;
1266+
control->segment_header.size = size;
12741267
control->handle = control_handle;
1268+
control->init_segment_size = init_segment_size;
1269+
control->max_segment_size = max_segment_size;
12751270
control->max_total_segment_size = (size_t) -1;
12761271
control->total_segment_size = size;
12771272
control->segment_handles[0] = control_handle;
@@ -2127,9 +2122,9 @@ make_new_segment(dsa_area *area, size_t requested_pages)
21272122
* move to huge pages in the future. Then we work back to the number of
21282123
* pages we can fit.
21292124
*/
2130-
total_size = DSA_INITIAL_SEGMENT_SIZE *
2125+
total_size = area->control->init_segment_size *
21312126
((size_t) 1 << (new_index / DSA_NUM_SEGMENTS_AT_EACH_SIZE));
2132-
total_size = Min(total_size, DSA_MAX_SEGMENT_SIZE);
2127+
total_size = Min(total_size, area->control->max_segment_size);
21332128
total_size = Min(total_size,
21342129
area->control->max_total_segment_size -
21352130
area->control->total_segment_size);

src/include/utils/dsa.h

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,31 @@ typedef pg_atomic_uint64 dsa_pointer_atomic;
7777
/* A sentinel value for dsa_pointer used to indicate failure to allocate. */
7878
#define InvalidDsaPointer ((dsa_pointer) 0)
7979

80+
/*
81+
* The number of bits used to represent the offset part of a dsa_pointer.
82+
* This controls the maximum size of a segment, the maximum possible
83+
* allocation size and also the maximum number of segments per area.
84+
*/
85+
#if SIZEOF_DSA_POINTER == 4
86+
#define DSA_OFFSET_WIDTH 27 /* 32 segments of size up to 128MB */
87+
#else
88+
#define DSA_OFFSET_WIDTH 40 /* 1024 segments of size up to 1TB */
89+
#endif
90+
91+
/*
92+
* The default size of the initial DSM segment that backs a dsa_area created
93+
* by dsa_create. After creating some number of segments of the initial size
94+
* we'll double this size, and so on. Larger segments may be created if
95+
* necessary to satisfy large requests.
96+
*/
97+
#define DSA_DEFAULT_INIT_SEGMENT_SIZE ((size_t) (1 * 1024 * 1024))
98+
99+
/* The minimum size of a DSM segment. */
100+
#define DSA_MIN_SEGMENT_SIZE ((size_t) (256 * 1024L))
101+
102+
/* The maximum size of a DSM segment. */
103+
#define DSA_MAX_SEGMENT_SIZE ((size_t) 1 << DSA_OFFSET_WIDTH)
104+
80105
/* Check if a dsa_pointer value is valid. */
81106
#define DsaPointerIsValid(x) ((x) != InvalidDsaPointer)
82107

@@ -88,6 +113,17 @@ typedef pg_atomic_uint64 dsa_pointer_atomic;
88113
#define dsa_allocate0(area, size) \
89114
dsa_allocate_extended(area, size, DSA_ALLOC_ZERO)
90115

116+
/* Create dsa_area with default segment sizes */
117+
#define dsa_create(tranch_id) \
118+
dsa_create_ext(tranch_id, DSA_DEFAULT_INIT_SEGMENT_SIZE, \
119+
DSA_MAX_SEGMENT_SIZE)
120+
121+
/* Create dsa_area with default segment sizes in an existing share memory space */
122+
#define dsa_create_in_place(place, size, tranch_id, segment) \
123+
dsa_create_in_place_ext(place, size, tranch_id, segment, \
124+
DSA_DEFAULT_INIT_SEGMENT_SIZE, \
125+
DSA_MAX_SEGMENT_SIZE)
126+
91127
/*
92128
* The type used for dsa_area handles. dsa_handle values can be shared with
93129
* other processes, so that they can attach to them. This provides a way to
@@ -102,10 +138,12 @@ typedef dsm_handle dsa_handle;
102138
/* Sentinel value to use for invalid dsa_handles. */
103139
#define DSA_HANDLE_INVALID ((dsa_handle) DSM_HANDLE_INVALID)
104140

105-
106-
extern dsa_area *dsa_create(int tranche_id);
107-
extern dsa_area *dsa_create_in_place(void *place, size_t size,
108-
int tranche_id, dsm_segment *segment);
141+
extern dsa_area *dsa_create_ext(int tranche_id, size_t init_segment_size,
142+
size_t max_segment_size);
143+
extern dsa_area *dsa_create_in_place_ext(void *place, size_t size,
144+
int tranche_id, dsm_segment *segment,
145+
size_t init_segment_size,
146+
size_t max_segment_size);
109147
extern dsa_area *dsa_attach(dsa_handle handle);
110148
extern dsa_area *dsa_attach_in_place(void *place, dsm_segment *segment);
111149
extern void dsa_release_in_place(void *place);

0 commit comments

Comments
 (0)