Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2d8f56d

Browse files
Rethink create and attach APIs of shared TidStore.
Previously, the behavior of TidStoreCreate() was inconsistent betweenlocal and shared TidStore instances in terms of memory limitation. Forlocal TidStore, a memory context was created with initial and maximummemory block sizes, as well as a minimum memory context size, based onthe specified max_bytes values. However, for shared TidStore, theprovided DSA area was used for TID storage. Although commitbb952c8allowed specifying the initial and maximum DSA segment sizes, callerswould have needed to clamp their own limits, which was not consistentand user-friendly.With this commit, when creating a shared TidStore, a dedicated DSAarea is created for TID storage instead of using a provided DSAarea. The initial and maximum DSA segment sizes are chosen based onthe specified max_bytes. Other processes can attach to the sharedTidStore using the handle of the created DSA returned by the newTidStoreGetDSA() function and the DSA pointer returned byTidStoreGetHandle(). The created DSA has the same lifetime as theshared TidStore and is deleted when all processes detach from it.To improve clarity, the TidStoreCreate() function has been dividedinto two separate functions: TidStoreCreateLocal() andTidStoreCreateShared().Reviewed-by: John NaylorDiscussion:https://postgr.es/m/CAD21AoAyc1j%3DBCdUqZfk6qbdjZ68UgRx1Gkpk0oah4K7S0Ri9g%40mail.gmail.com
1 parentd1cf531 commit2d8f56d

File tree

3 files changed

+89
-39
lines changed

3 files changed

+89
-39
lines changed

‎src/backend/access/common/tidstore.c

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
* Internally it uses a radix tree as the storage for TIDs. The key is the
88
* BlockNumber and the value is a bitmap of offsets, BlocktableEntry.
99
*
10-
* TidStore can be shared among parallel worker processes bypassing DSA area
11-
*to TidStoreCreate(). Other backends can attach to the shared TidStore by
12-
* TidStoreAttach().
10+
* TidStore can be shared among parallel worker processes byusing
11+
*TidStoreCreateShared(). Other backends can attach to the shared TidStore
12+
*byTidStoreAttach().
1313
*
1414
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
1515
* Portions Copyright (c) 1994, Regents of the University of California
@@ -111,15 +111,16 @@ static void tidstore_iter_extract_tids(TidStoreIter *iter, BlockNumber blkno,
111111
/*
112112
* Create a TidStore. The TidStore will live in the memory context that is
113113
* CurrentMemoryContext at the time of this call. The TID storage, backed
114-
* by a radix tree, will live in its child memory context, rt_context. The
115-
* TidStore will be limited to (approximately) max_bytes total memory
116-
* consumption. If the 'area' is non-NULL, the radix tree is created in the
117-
* DSA area.
114+
* by a radix tree, will live in its child memory context, rt_context.
118115
*
119-
* The returned object is allocated in backend-local memory.
116+
* "max_bytes" is not an internally-enforced limit; it is used only as a
117+
* hint to cap the memory block size of the memory context for TID storage.
118+
* This reduces space wastage due to over-allocation. If the caller wants to
119+
* monitor memory usage, it must compare its limit with the value reported
120+
* by TidStoreMemoryUsage().
120121
*/
121122
TidStore*
122-
TidStoreCreate(size_tmax_bytes,dsa_area*area,inttranche_id)
123+
TidStoreCreateLocal(size_tmax_bytes)
123124
{
124125
TidStore*ts;
125126
size_tinitBlockSize=ALLOCSET_DEFAULT_INITSIZE;
@@ -143,33 +144,74 @@ TidStoreCreate(size_t max_bytes, dsa_area *area, int tranche_id)
143144
initBlockSize,
144145
maxBlockSize);
145146

146-
if (area!=NULL)
147-
{
148-
ts->tree.shared=shared_ts_create(ts->rt_context,area,
149-
tranche_id);
150-
ts->area=area;
151-
}
152-
else
153-
ts->tree.local=local_ts_create(ts->rt_context);
147+
ts->tree.local=local_ts_create(ts->rt_context);
154148

155149
returnts;
156150
}
157151

158152
/*
159-
* Attach to the shared TidStore using the given handle. The returned object
160-
* is allocated in backend-local memory using the CurrentMemoryContext.
153+
* Similar to TidStoreCreateLocal() but create a shared TidStore on a
154+
* DSA area. The TID storage will live in the DSA area, and the memory
155+
* context rt_context will have only meta data of the radix tree.
156+
*
157+
* The returned object is allocated in backend-local memory.
161158
*/
162159
TidStore*
163-
TidStoreAttach(dsa_area*area,dsa_pointerhandle)
160+
TidStoreCreateShared(size_tmax_bytes,inttranche_id)
164161
{
165162
TidStore*ts;
163+
dsa_area*area;
164+
size_tdsa_init_size=DSA_DEFAULT_INIT_SEGMENT_SIZE;
165+
size_tdsa_max_size=DSA_MAX_SEGMENT_SIZE;
166166

167-
Assert(area!=NULL);
167+
ts=palloc0(sizeof(TidStore));
168+
ts->context=CurrentMemoryContext;
169+
170+
ts->rt_context=AllocSetContextCreate(CurrentMemoryContext,
171+
"TID storage meta data",
172+
ALLOCSET_SMALL_SIZES);
173+
174+
/*
175+
* Choose the initial and maximum DSA segment sizes to be no longer than
176+
* 1/8 of max_bytes.
177+
*/
178+
while (8*dsa_max_size>max_bytes)
179+
dsa_max_size >>=1;
180+
181+
if (dsa_max_size<DSA_MIN_SEGMENT_SIZE)
182+
dsa_max_size=DSA_MIN_SEGMENT_SIZE;
183+
184+
if (dsa_init_size>dsa_max_size)
185+
dsa_init_size=dsa_max_size;
186+
187+
area=dsa_create_ext(tranche_id,dsa_init_size,dsa_max_size);
188+
ts->tree.shared=shared_ts_create(ts->rt_context,area,
189+
tranche_id);
190+
ts->area=area;
191+
192+
returnts;
193+
}
194+
195+
/*
196+
* Attach to the shared TidStore. 'area_handle' is the DSA handle where
197+
* the TidStore is created. 'handle' is the dsa_pointer returned by
198+
* TidStoreGetHandle(). The returned object is allocated in backend-local
199+
* memory using the CurrentMemoryContext.
200+
*/
201+
TidStore*
202+
TidStoreAttach(dsa_handlearea_handle,dsa_pointerhandle)
203+
{
204+
TidStore*ts;
205+
dsa_area*area;
206+
207+
Assert(area_handle!=DSA_HANDLE_INVALID);
168208
Assert(DsaPointerIsValid(handle));
169209

170210
/* create per-backend state */
171211
ts=palloc0(sizeof(TidStore));
172212

213+
area=dsa_attach(area_handle);
214+
173215
/* Find the shared the shared radix tree */
174216
ts->tree.shared=shared_ts_attach(area,handle);
175217
ts->area=area;
@@ -178,17 +220,17 @@ TidStoreAttach(dsa_area *area, dsa_pointer handle)
178220
}
179221

180222
/*
181-
* Detach from a TidStore. This detaches from radix tree and frees the
182-
* backend-local resources. The radix tree will continue to exist until
183-
* it is either explicitly destroyed, or the area that backs it is returned
184-
* to the operating system.
223+
* Detach from a TidStore. This also detaches from radix tree and frees
224+
* the backend-local resources.
185225
*/
186226
void
187227
TidStoreDetach(TidStore*ts)
188228
{
189229
Assert(TidStoreIsShared(ts));
190230

191231
shared_ts_detach(ts->tree.shared);
232+
dsa_detach(ts->area);
233+
192234
pfree(ts);
193235
}
194236

@@ -234,7 +276,11 @@ TidStoreDestroy(TidStore *ts)
234276
{
235277
/* Destroy underlying radix tree */
236278
if (TidStoreIsShared(ts))
279+
{
237280
shared_ts_free(ts->tree.shared);
281+
282+
dsa_detach(ts->area);
283+
}
238284
else
239285
local_ts_free(ts->tree.local);
240286

@@ -420,6 +466,17 @@ TidStoreMemoryUsage(TidStore *ts)
420466
returnlocal_ts_memory_usage(ts->tree.local);
421467
}
422468

469+
/*
470+
* Return the DSA area where the TidStore lives.
471+
*/
472+
dsa_area*
473+
TidStoreGetDSA(TidStore*ts)
474+
{
475+
Assert(TidStoreIsShared(ts));
476+
477+
returnts->area;
478+
}
479+
423480
dsa_pointer
424481
TidStoreGetHandle(TidStore*ts)
425482
{

‎src/include/access/tidstore.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ typedef struct TidStoreIterResult
2929
OffsetNumber*offsets;
3030
}TidStoreIterResult;
3131

32-
externTidStore*TidStoreCreate(size_tmax_bytes,dsa_area*area,
33-
inttranche_id);
34-
externTidStore*TidStoreAttach(dsa_area*area,dsa_pointerhandle);
32+
externTidStore*TidStoreCreateLocal(size_tmax_bytes);
33+
externTidStore*TidStoreCreateShared(size_tmax_bytes,inttranche_id);
34+
externTidStore*TidStoreAttach(dsa_handlearea_handle,dsa_pointerhandle);
3535
externvoidTidStoreDetach(TidStore*ts);
3636
externvoidTidStoreLockExclusive(TidStore*ts);
3737
externvoidTidStoreLockShare(TidStore*ts);
@@ -45,5 +45,6 @@ extern TidStoreIterResult *TidStoreIterateNext(TidStoreIter *iter);
4545
externvoidTidStoreEndIterate(TidStoreIter*iter);
4646
externsize_tTidStoreMemoryUsage(TidStore*ts);
4747
externdsa_pointerTidStoreGetHandle(TidStore*ts);
48+
externdsa_area*TidStoreGetDSA(TidStore*ts);
4849

4950
#endif/* TIDSTORE_H */

‎src/test/modules/test_tidstore/test_tidstore.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ PG_FUNCTION_INFO_V1(test_is_full);
3434
PG_FUNCTION_INFO_V1(test_destroy);
3535

3636
staticTidStore*tidstore=NULL;
37-
staticdsa_area*dsa=NULL;
3837
staticsize_ttidstore_empty_size;
3938

4039
/* array for verification of some tests */
@@ -94,7 +93,6 @@ test_create(PG_FUNCTION_ARGS)
9493
size_tarray_init_size=1024;
9594

9695
Assert(tidstore==NULL);
97-
Assert(dsa==NULL);
9896

9997
/*
10098
* Create the TidStore on TopMemoryContext so that the same process use it
@@ -109,18 +107,16 @@ test_create(PG_FUNCTION_ARGS)
109107
tranche_id=LWLockNewTrancheId();
110108
LWLockRegisterTranche(tranche_id,"test_tidstore");
111109

112-
dsa=dsa_create(tranche_id);
110+
tidstore=TidStoreCreateShared(tidstore_max_size,tranche_id);
113111

114112
/*
115113
* Remain attached until end of backend or explicitly detached so that
116114
* the same process use the tidstore for subsequent tests.
117115
*/
118-
dsa_pin_mapping(dsa);
119-
120-
tidstore=TidStoreCreate(tidstore_max_size,dsa,tranche_id);
116+
dsa_pin_mapping(TidStoreGetDSA(tidstore));
121117
}
122118
else
123-
tidstore=TidStoreCreate(tidstore_max_size,NULL,0);
119+
tidstore=TidStoreCreateLocal(tidstore_max_size);
124120

125121
tidstore_empty_size=TidStoreMemoryUsage(tidstore);
126122

@@ -309,9 +305,5 @@ test_destroy(PG_FUNCTION_ARGS)
309305
pfree(items.lookup_tids);
310306
pfree(items.iter_tids);
311307

312-
if (dsa)
313-
dsa_detach(dsa);
314-
dsa=NULL;
315-
316308
PG_RETURN_VOID();
317309
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp