Skip to content

Commit 1a6be1c

Browse files
committed
fix up earlier comments, standardize instrumentation for parallel workers
1 parent 10d1b3a commit 1a6be1c

16 files changed

Lines changed: 373 additions & 458 deletions

src/backend/access/heap/heapam.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,8 +1321,8 @@ heap_beginscan(Relation relation, Snapshot snapshot,
13211321
/*
13221322
* The caller (the executor) always supplies the location where the
13231323
* statistics should be accumulated -- the node's own storage, or a
1324-
* parallel worker's slot in shared memory -- so the scan never owns the
1325-
* instrumentation and never frees it.
1324+
* parallel worker's slot in shared memory -- so the scan never owns
1325+
* the instrumentation and never frees it.
13261326
*/
13271327
Assert(instrument != NULL);
13281328
scan->rs_base.rs_instrument = instrument;

src/backend/commands/explain.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3150,7 +3150,8 @@ show_sort_info(SortState *sortstate, ExplainState *es)
31503150
const char *spaceType;
31513151
int64 spaceUsed;
31523152

3153-
sinstrument = &sortstate->shared_info->sinstrument[n];
3153+
sinstrument = GetWorkerInstr(sortstate->shared_info,
3154+
TuplesortInstrumentation, n);
31543155
if (sinstrument->sortMethod == SORT_TYPE_STILL_IN_PROGRESS)
31553156
continue; /* ignore any unfilled slots */
31563157
sortMethod = tuplesort_method_name(sinstrument->sortMethod);
@@ -3345,7 +3346,7 @@ show_incremental_sort_info(IncrementalSortState *incrsortstate,
33453346
for (n = 0; n < incrsortstate->shared_info->num_workers; n++)
33463347
{
33473348
IncrementalSortInfo *incsort_info =
3348-
&incrsortstate->shared_info->sinfo[n];
3349+
GetWorkerInstr(incrsortstate->shared_info, IncrementalSortInfo, n);
33493350

33503351
/*
33513352
* If a worker hasn't processed any sort groups at all, then
@@ -3421,7 +3422,8 @@ show_hash_info(HashState *hashstate, ExplainState *es)
34213422

34223423
for (i = 0; i < shared_info->num_workers; ++i)
34233424
{
3424-
HashInstrumentation *worker_hi = &shared_info->hinstrument[i];
3425+
HashInstrumentation *worker_hi = GetWorkerInstr(shared_info,
3426+
HashInstrumentation, i);
34253427

34263428
hinstrument.nbuckets = Max(hinstrument.nbuckets,
34273429
worker_hi->nbuckets);
@@ -3697,7 +3699,7 @@ show_memoize_info(MemoizeState *mstate, List *ancestors, ExplainState *es)
36973699
{
36983700
MemoizeInstrumentation *si;
36993701

3700-
si = &mstate->shared_info->sinstrument[n];
3702+
si = GetWorkerInstr(mstate->shared_info, MemoizeInstrumentation, n);
37013703

37023704
/*
37033705
* Skip workers that didn't do any work. We needn't bother checking
@@ -3827,7 +3829,8 @@ show_hashagg_info(AggState *aggstate, ExplainState *es)
38273829
uint64 hash_disk_used;
38283830
int hash_batches_used;
38293831

3830-
sinstrument = &aggstate->shared_info->sinstrument[n];
3832+
sinstrument = GetWorkerInstr(aggstate->shared_info,
3833+
AggregateInstrumentation, n);
38313834
/* Skip workers that didn't do anything */
38323835
if (sinstrument->hash_mem_peak == 0)
38333836
continue;
@@ -3916,7 +3919,8 @@ show_indexsearches_info(PlanState *planstate, ExplainState *es)
39163919
{
39173920
for (int i = 0; i < SharedInfo->num_workers; ++i)
39183921
{
3919-
IndexScanInstrumentation *winstrument = &SharedInfo->winstrument[i];
3922+
IndexScanInstrumentation *winstrument =
3923+
GetWorkerInstr(SharedInfo, IndexScanInstrumentation, i);
39203924

39213925
nsearches += winstrument->nsearches;
39223926
}
@@ -3960,7 +3964,9 @@ show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es)
39603964
{
39613965
for (int n = 0; n < planstate->sinstrument->num_workers; n++)
39623966
{
3963-
BitmapHeapScanInstrumentation *si = &planstate->sinstrument->sinstrument[n];
3967+
BitmapHeapScanInstrumentation *si =
3968+
GetWorkerInstr(planstate->sinstrument,
3969+
BitmapHeapScanInstrumentation, n);
39643970

39653971
if (si->exact_pages == 0 && si->lossy_pages == 0)
39663972
continue;
@@ -4091,7 +4097,9 @@ show_scan_io_usage(ScanState *planstate, ExplainState *es)
40914097
{
40924098
for (int i = 0; i < sinstrument->num_workers; ++i)
40934099
{
4094-
BitmapHeapScanInstrumentation *winstrument = &sinstrument->sinstrument[i];
4100+
BitmapHeapScanInstrumentation *winstrument =
4101+
GetWorkerInstr(sinstrument,
4102+
BitmapHeapScanInstrumentation, i);
40954103

40964104
AccumulateIOStats(&stats, &winstrument->stats.io);
40974105

@@ -4115,7 +4123,8 @@ show_scan_io_usage(ScanState *planstate, ExplainState *es)
41154123
{
41164124
for (int i = 0; i < sinstrument->num_workers; ++i)
41174125
{
4118-
SeqScanInstrumentation *winstrument = &sinstrument->sinstrument[i];
4126+
SeqScanInstrumentation *winstrument =
4127+
GetWorkerInstr(sinstrument, SeqScanInstrumentation, i);
41194128

41204129
AccumulateIOStats(&stats, &winstrument->stats.io);
41214130

@@ -4139,7 +4148,9 @@ show_scan_io_usage(ScanState *planstate, ExplainState *es)
41394148
{
41404149
for (int i = 0; i < sinstrument->num_workers; ++i)
41414150
{
4142-
TidRangeScanInstrumentation *winstrument = &sinstrument->sinstrument[i];
4151+
TidRangeScanInstrumentation *winstrument =
4152+
GetWorkerInstr(sinstrument,
4153+
TidRangeScanInstrumentation, i);
41434154

41444155
AccumulateIOStats(&stats, &winstrument->stats.io);
41454156

src/backend/executor/execParallel.c

Lines changed: 84 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct SharedExecutorInstrumentation
110110
* follows.
111111
*/
112112
};
113+
113114
/*
114115
* While the query runs, each parallel worker writes its per-node statistics
115116
* directly into its own slot in this array (indexed by ParallelWorkerNumber),
@@ -252,6 +253,67 @@ ExecSerializePlan(Plan *plan, EState *estate)
252253
* While we're at it, count the number of PlanState nodes in the tree, so
253254
* we know how many Instrumentation structures we need.
254255
*/
256+
257+
/*
258+
* Generic helpers for per-worker node instrumentation containers.
259+
*
260+
* Many node types collect a fixed-size instrumentation struct per parallel
261+
* worker in a SharedWorkerInstrumentation container (see instrument_node.h).
262+
* These helpers factor out the identical estimate/allocate/lookup/retrieve
263+
* plumbing; only the element size, the TOC key, and the gating conditions vary
264+
* between nodes, and those stay in the per-node callers.
265+
*/
266+
267+
/* Reserve DSM space (one chunk + one key) for the container. */
268+
void
269+
ExecInstrEstimate(ParallelContext *pcxt, Size elemsz)
270+
{
271+
shm_toc_estimate_chunk(&pcxt->estimator,
272+
SharedWorkerInstrSize(pcxt->nworkers, elemsz));
273+
shm_toc_estimate_keys(&pcxt->estimator, 1);
274+
}
275+
276+
/* Allocate, zero, and publish the container under 'key'; returns it. */
277+
SharedWorkerInstrumentation *
278+
ExecInstrInitDSM(ParallelContext *pcxt, uint64 key, Size elemsz)
279+
{
280+
Size size = SharedWorkerInstrSize(pcxt->nworkers, elemsz);
281+
SharedWorkerInstrumentation *si = shm_toc_allocate(pcxt->toc, size);
282+
283+
/* ensure any unfilled slots will contain zeroes */
284+
memset(si, 0, size);
285+
si->num_workers = pcxt->nworkers;
286+
shm_toc_insert(pcxt->toc, key, si);
287+
return si;
288+
}
289+
290+
/* Worker side: look up the container previously published under 'key'. */
291+
SharedWorkerInstrumentation *
292+
ExecInstrInitWorker(shm_toc *toc, uint64 key, bool missing_ok)
293+
{
294+
return (SharedWorkerInstrumentation *) shm_toc_lookup(toc, key, missing_ok);
295+
}
296+
297+
/*
298+
* Leader side: copy the container out of (soon to be freed) DSM into a
299+
* backend-local copy, so EXPLAIN can read it after the parallel context is
300+
* torn down. Returns NULL if there was no instrumentation.
301+
*/
302+
SharedWorkerInstrumentation *
303+
ExecInstrRetrieve(SharedWorkerInstrumentation * shared, Size elemsz)
304+
{
305+
Size size;
306+
SharedWorkerInstrumentation *si;
307+
308+
if (shared == NULL)
309+
return NULL;
310+
311+
size = SharedWorkerInstrSize(shared->num_workers, elemsz);
312+
si = palloc(size);
313+
memcpy(si, shared, size);
314+
return si;
315+
}
316+
255317
static bool
256318
ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e)
257319
{
@@ -873,10 +935,11 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
873935
instrumentation->num_plan_nodes = e.nnodes;
874936

875937
/*
876-
* Initialize each worker's slot. Workers write into these directly as
877-
* the query runs and never reset them, so this must happen exactly once
878-
* (not on relaunch, where the slots accumulate across rounds). The
879-
* async_mode flag is fixed up by each worker once it knows its node.
938+
* Initialize each worker's slot. Workers write into these directly
939+
* as the query runs and never reset them, so this must happen exactly
940+
* once (not on relaunch, where the slots accumulate across rounds).
941+
* The async_mode flag is fixed up by each worker once it knows its
942+
* node.
880943
*/
881944
for (node = 0; node < e.nnodes; ++node)
882945
for (worker = 0; worker < nworkers; ++worker)
@@ -1127,9 +1190,9 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate,
11271190
elog(ERROR, "plan node %d not found", plan_node_id);
11281191

11291192
/*
1130-
* Accumulate the statistics from all workers. The workers already flushed
1131-
* their final cycle with InstrEndLoop before exiting, so no InstrEndLoop is
1132-
* needed here.
1193+
* Accumulate the statistics from all workers. The workers already
1194+
* flushed their final cycle with InstrEndLoop before exiting, so no
1195+
* InstrEndLoop is needed here.
11331196
*/
11341197
for (n = 0; n < instrumentation->num_workers; ++n)
11351198
InstrAggNode(planstate->instrument,
@@ -1412,9 +1475,9 @@ ExecParallelRepointInstrumentation(PlanState *planstate,
14121475

14131476
/*
14141477
* The leader initialized the slot's options but cannot know each node's
1415-
* async mode, so carry that over from the local instrumentation. We do not
1416-
* otherwise reset the slot: when workers are relaunched (e.g. a rescanned
1417-
* Gather) the slots accumulate across rounds.
1478+
* async mode, so carry that over from the local instrumentation. We do
1479+
* not otherwise reset the slot: when workers are relaunched (e.g. a
1480+
* rescanned Gather) the slots accumulate across rounds.
14181481
*/
14191482
slot->async_mode = planstate->instrument->async_mode;
14201483

@@ -1455,10 +1518,11 @@ ExecParallelInitializeWorker(PlanState *planstate, ParallelWorkerContext *pwcxt)
14551518
switch (nodeTag(planstate))
14561519
{
14571520
case T_SeqScanState:
1521+
14581522
/*
14591523
* Set up instrumentation first (even when not parallel-aware, for
1460-
* EXPLAIN ANALYZE) so that a parallel-aware scan can be pointed at
1461-
* the worker's shared I/O stats slot when it begins.
1524+
* EXPLAIN ANALYZE) so that a parallel-aware scan can be pointed
1525+
* at the worker's shared I/O stats slot when it begins.
14621526
*/
14631527
ExecSeqScanInstrumentInitWorker((SeqScanState *) planstate, pwcxt);
14641528
if (planstate->plan->parallel_aware)
@@ -1491,10 +1555,11 @@ ExecParallelInitializeWorker(PlanState *planstate, ParallelWorkerContext *pwcxt)
14911555
pwcxt);
14921556
break;
14931557
case T_TidRangeScanState:
1558+
14941559
/*
14951560
* Set up instrumentation first (even when not parallel-aware, for
1496-
* EXPLAIN ANALYZE) so that a parallel-aware scan can be pointed at
1497-
* the worker's shared I/O stats slot when it begins.
1561+
* EXPLAIN ANALYZE) so that a parallel-aware scan can be pointed
1562+
* at the worker's shared I/O stats slot when it begins.
14981563
*/
14991564
ExecTidRangeScanInstrumentInitWorker((TidRangeScanState *) planstate,
15001565
pwcxt);
@@ -1624,9 +1689,9 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
16241689
ExecParallelInitializeWorker(queryDesc->planstate, &pwcxt);
16251690

16261691
/*
1627-
* If instrumentation is enabled, point each node's instrumentation at this
1628-
* worker's slot in shared memory so the executor writes statistics there
1629-
* directly, with no copy needed at shutdown.
1692+
* If instrumentation is enabled, point each node's instrumentation at
1693+
* this worker's slot in shared memory so the executor writes statistics
1694+
* there directly, with no copy needed at shutdown.
16301695
*/
16311696
if (instrumentation != NULL)
16321697
ExecParallelRepointInstrumentation(queryDesc->planstate, instrumentation);
@@ -1662,8 +1727,8 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
16621727

16631728
/*
16641729
* Finalize instrumentation if any instrumentation options are set. The
1665-
* statistics were written straight into shared memory during execution, so
1666-
* this just flushes each node's final run cycle.
1730+
* statistics were written straight into shared memory during execution,
1731+
* so this just flushes each node's final run cycle.
16671732
*/
16681733
if (instrumentation != NULL)
16691734
ExecParallelFinishInstrumentation(queryDesc->planstate, NULL);

0 commit comments

Comments
 (0)