From afdeaf12ab7038574912e9469f4ad97ab1d3c83e Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Sun, 5 Apr 2026 16:27:22 -0400 Subject: [PATCH v8-alt 3/7] fix bhs non-parallel-aware explain analyze --- src/backend/commands/explain.c | 2 +- src/backend/executor/execParallel.c | 9 ++ src/backend/executor/nodeBitmapHeapscan.c | 100 ++++++++++++---------- src/include/executor/nodeBitmapHeapscan.h | 6 ++ 4 files changed, 72 insertions(+), 45 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index e4b70166b0e..8275bb2af61 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -3949,7 +3949,7 @@ show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es) } /* Display stats for each parallel worker */ - if (planstate->pstate != NULL) + if (planstate->sinstrument != NULL) { for (int n = 0; n < planstate->sinstrument->num_workers; n++) { diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index 10d2909892c..8d5c69ec85e 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -299,6 +299,9 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e) if (planstate->plan->parallel_aware) ExecBitmapHeapEstimate((BitmapHeapScanState *) planstate, e->pcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecBitmapHeapInstrumentEstimate((BitmapHeapScanState *) planstate, + e->pcxt); break; case T_HashJoinState: if (planstate->plan->parallel_aware) @@ -538,6 +541,9 @@ ExecParallelInitializeDSM(PlanState *planstate, if (planstate->plan->parallel_aware) ExecBitmapHeapInitializeDSM((BitmapHeapScanState *) planstate, d->pcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecBitmapHeapInstrumentInitDSM((BitmapHeapScanState *) planstate, + d->pcxt); break; case T_HashJoinState: if (planstate->plan->parallel_aware) @@ -1423,6 +1429,9 @@ ExecParallelInitializeWorker(PlanState *planstate, ParallelWorkerContext *pwcxt) if (planstate->plan->parallel_aware) ExecBitmapHeapInitializeWorker((BitmapHeapScanState *) planstate, pwcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecBitmapHeapInstrumentInitWorker((BitmapHeapScanState *) planstate, + pwcxt); break; case T_HashJoinState: if (planstate->plan->parallel_aware) diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 73831aed451..4b1bff61214 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -38,6 +38,7 @@ #include "access/relscan.h" #include "access/tableam.h" #include "access/visibilitymap.h" +#include "executor/execParallel.h" #include "executor/executor.h" #include "executor/instrument.h" #include "executor/nodeBitmapHeapscan.h" @@ -495,18 +496,8 @@ void ExecBitmapHeapEstimate(BitmapHeapScanState *node, ParallelContext *pcxt) { - Size size; - - size = MAXALIGN(sizeof(ParallelBitmapHeapState)); - - /* account for instrumentation, if required */ - if (node->ss.ps.instrument && pcxt->nworkers > 0) - { - size = add_size(size, offsetof(SharedBitmapHeapInstrumentation, sinstrument)); - size = add_size(size, mul_size(pcxt->nworkers, sizeof(BitmapHeapScanInstrumentation))); - } - - shm_toc_estimate_chunk(&pcxt->estimator, size); + shm_toc_estimate_chunk(&pcxt->estimator, + MAXALIGN(sizeof(ParallelBitmapHeapState))); shm_toc_estimate_keys(&pcxt->estimator, 1); } @@ -521,27 +512,14 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node, ParallelContext *pcxt) { ParallelBitmapHeapState *pstate; - SharedBitmapHeapInstrumentation *sinstrument = NULL; dsa_area *dsa = node->ss.ps.state->es_query_dsa; - char *ptr; - Size size; /* If there's no DSA, there are no workers; initialize nothing. */ if (dsa == NULL) return; - size = MAXALIGN(sizeof(ParallelBitmapHeapState)); - if (node->ss.ps.instrument && pcxt->nworkers > 0) - { - size = add_size(size, offsetof(SharedBitmapHeapInstrumentation, sinstrument)); - size = add_size(size, mul_size(pcxt->nworkers, sizeof(BitmapHeapScanInstrumentation))); - } - - ptr = shm_toc_allocate(pcxt->toc, size); - pstate = (ParallelBitmapHeapState *) ptr; - ptr += MAXALIGN(sizeof(ParallelBitmapHeapState)); - if (node->ss.ps.instrument && pcxt->nworkers > 0) - sinstrument = (SharedBitmapHeapInstrumentation *) ptr; + pstate = (ParallelBitmapHeapState *) + shm_toc_allocate(pcxt->toc, MAXALIGN(sizeof(ParallelBitmapHeapState))); pstate->tbmiterator = 0; @@ -551,18 +529,8 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node, ConditionVariableInit(&pstate->cv); - if (sinstrument) - { - sinstrument->num_workers = pcxt->nworkers; - - /* ensure any unfilled slots will contain zeroes */ - memset(sinstrument->sinstrument, 0, - pcxt->nworkers * sizeof(BitmapHeapScanInstrumentation)); - } - shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate); node->pstate = pstate; - node->sinstrument = sinstrument; } /* ---------------------------------------------------------------- @@ -600,17 +568,61 @@ void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node, ParallelWorkerContext *pwcxt) { - char *ptr; - Assert(node->ss.ps.state->es_query_dsa != NULL); - ptr = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false); + node->pstate = (ParallelBitmapHeapState *) + shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false); +} + +void +ExecBitmapHeapInstrumentEstimate(BitmapHeapScanState *node, + ParallelContext *pcxt) +{ + Size size; + + /* don't need this if not instrumenting or no workers */ + if (!node->ss.ps.instrument || pcxt->nworkers == 0) + return; + + size = offsetof(SharedBitmapHeapInstrumentation, sinstrument) + + pcxt->nworkers * sizeof(BitmapHeapScanInstrumentation); + shm_toc_estimate_chunk(&pcxt->estimator, size); + shm_toc_estimate_keys(&pcxt->estimator, 1); +} - node->pstate = (ParallelBitmapHeapState *) ptr; - ptr += MAXALIGN(sizeof(ParallelBitmapHeapState)); +void +ExecBitmapHeapInstrumentInitDSM(BitmapHeapScanState *node, + ParallelContext *pcxt) +{ + Size size; + + /* don't need this if not instrumenting or no workers */ + if (!node->ss.ps.instrument || pcxt->nworkers == 0) + return; - if (node->ss.ps.instrument) - node->sinstrument = (SharedBitmapHeapInstrumentation *) ptr; + size = offsetof(SharedBitmapHeapInstrumentation, sinstrument) + + pcxt->nworkers * sizeof(BitmapHeapScanInstrumentation); + node->sinstrument = + (SharedBitmapHeapInstrumentation *) shm_toc_allocate(pcxt->toc, size); + + /* Each per-worker area must start out as zeroes */ + memset(node->sinstrument, 0, size); + node->sinstrument->num_workers = pcxt->nworkers; + shm_toc_insert(pcxt->toc, + node->ss.ps.plan->plan_node_id + + PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET, + node->sinstrument); +} + +void +ExecBitmapHeapInstrumentInitWorker(BitmapHeapScanState *node, + ParallelWorkerContext *pwcxt) +{ + node->sinstrument = (SharedBitmapHeapInstrumentation *) + shm_toc_lookup(pwcxt->toc, + node->ss.ps.plan->plan_node_id + + PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET, + true); } /* ---------------------------------------------------------------- diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h index 5d82f71abff..5c0b6592a1f 100644 --- a/src/include/executor/nodeBitmapHeapscan.h +++ b/src/include/executor/nodeBitmapHeapscan.h @@ -28,6 +28,12 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node, ParallelContext *pcxt); extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node, ParallelWorkerContext *pwcxt); +extern void ExecBitmapHeapInstrumentEstimate(BitmapHeapScanState *node, + ParallelContext *pcxt); +extern void ExecBitmapHeapInstrumentInitDSM(BitmapHeapScanState *node, + ParallelContext *pcxt); +extern void ExecBitmapHeapInstrumentInitWorker(BitmapHeapScanState *node, + ParallelWorkerContext *pwcxt); extern void ExecBitmapHeapRetrieveInstrumentation(BitmapHeapScanState *node); #endif /* NODEBITMAPHEAPSCAN_H */ -- 2.43.0