Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5a1e6df

Browse files
committed
Show Parallel Bitmap Heap Scan worker stats in EXPLAIN ANALYZE
Nodes like Memoize report the cache stats for each parallel worker, so it makes sense to show the exact and lossy pages in Parallel Bitmap Heap Scan in a similar way. Likewise, Sort shows the method and memory used for each worker. There was some discussion on whether the leader stats should include the totals for each parallel worker or not. I did some analysis on this to see what other parallel node types do and it seems only Parallel Hash does anything like this. All the rest, per what's supported by ExecParallelRetrieveInstrumentation() are consistent with each other. Author: David Geier <geidav.pg@gmail.com> Author: Heikki Linnakangas <hlinnaka@iki.fi> Author: Donghang Lin <donghanglin@gmail.com> Author: Alena Rybakina <lena.ribackina@yandex.ru> Author: David Rowley <dgrowleyml@gmail.com> Reviewed-by: Dmitry Dolgov <9erthalion6@gmail.com> Reviewed-by: Michael Christofides <michael@pgmustard.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Dilip Kumar <dilipbalaut@gmail.com> Reviewed-by: Tomas Vondra <tomas.vondra@enterprisedb.com> Reviewed-by: Melanie Plageman <melanieplageman@gmail.com> Reviewed-by: Donghang Lin <donghanglin@gmail.com> Reviewed-by: Masahiro Ikeda <Masahiro.Ikeda@nttdata.com> Discussion: https://postgr.es/m/b3d80961-c2e5-38cc-6a32-61886cdf766d%40gmail.com
1 parent e41f713 commit 5a1e6df

File tree

6 files changed

+181
-23
lines changed

6 files changed

+181
-23
lines changed

src/backend/commands/explain.c

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,8 +2010,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
20102010
if (plan->qual)
20112011
show_instrumentation_count("Rows Removed by Filter", 1,
20122012
planstate, es);
2013-
if (es->analyze)
2014-
show_tidbitmap_info((BitmapHeapScanState *) planstate, es);
2013+
show_tidbitmap_info((BitmapHeapScanState *) planstate, es);
20152014
break;
20162015
case T_SampleScan:
20172016
show_tablesample(((SampleScan *) plan)->tablesample,
@@ -3628,31 +3627,70 @@ show_hashagg_info(AggState *aggstate, ExplainState *es)
36283627
}
36293628

36303629
/*
3631-
* If it's EXPLAIN ANALYZE, show exact/lossy pages for a BitmapHeapScan node
3630+
* Show exact/lossy pages for a BitmapHeapScan node
36323631
*/
36333632
static void
36343633
show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es)
36353634
{
3635+
if (!es->analyze)
3636+
return;
3637+
36363638
if (es->format != EXPLAIN_FORMAT_TEXT)
36373639
{
36383640
ExplainPropertyUInteger("Exact Heap Blocks", NULL,
3639-
planstate->exact_pages, es);
3641+
planstate->stats.exact_pages, es);
36403642
ExplainPropertyUInteger("Lossy Heap Blocks", NULL,
3641-
planstate->lossy_pages, es);
3643+
planstate->stats.lossy_pages, es);
36423644
}
36433645
else
36443646
{
3645-
if (planstate->exact_pages > 0 || planstate->lossy_pages > 0)
3647+
if (planstate->stats.exact_pages > 0 || planstate->stats.lossy_pages > 0)
36463648
{
36473649
ExplainIndentText(es);
36483650
appendStringInfoString(es->str, "Heap Blocks:");
3649-
if (planstate->exact_pages > 0)
3650-
appendStringInfo(es->str, " exact=" UINT64_FORMAT, planstate->exact_pages);
3651-
if (planstate->lossy_pages > 0)
3652-
appendStringInfo(es->str, " lossy=" UINT64_FORMAT, planstate->lossy_pages);
3651+
if (planstate->stats.exact_pages > 0)
3652+
appendStringInfo(es->str, " exact=" UINT64_FORMAT, planstate->stats.exact_pages);
3653+
if (planstate->stats.lossy_pages > 0)
3654+
appendStringInfo(es->str, " lossy=" UINT64_FORMAT, planstate->stats.lossy_pages);
36533655
appendStringInfoChar(es->str, '\n');
36543656
}
36553657
}
3658+
3659+
/* Display stats for each parallel worker */
3660+
if (planstate->pstate != NULL)
3661+
{
3662+
for (int n = 0; n < planstate->sinstrument->num_workers; n++)
3663+
{
3664+
BitmapHeapScanInstrumentation *si = &planstate->sinstrument->sinstrument[n];
3665+
3666+
if (si->exact_pages == 0 && si->lossy_pages == 0)
3667+
continue;
3668+
3669+
if (es->workers_state)
3670+
ExplainOpenWorker(n, es);
3671+
3672+
if (es->format == EXPLAIN_FORMAT_TEXT)
3673+
{
3674+
ExplainIndentText(es);
3675+
appendStringInfoString(es->str, "Heap Blocks:");
3676+
if (si->exact_pages > 0)
3677+
appendStringInfo(es->str, " exact=" UINT64_FORMAT, si->exact_pages);
3678+
if (si->lossy_pages > 0)
3679+
appendStringInfo(es->str, " lossy=" UINT64_FORMAT, si->lossy_pages);
3680+
appendStringInfoChar(es->str, '\n');
3681+
}
3682+
else
3683+
{
3684+
ExplainPropertyUInteger("Exact Heap Blocks", NULL,
3685+
si->exact_pages, es);
3686+
ExplainPropertyUInteger("Lossy Heap Blocks", NULL,
3687+
si->lossy_pages, es);
3688+
}
3689+
3690+
if (es->workers_state)
3691+
ExplainCloseWorker(n, es);
3692+
}
3693+
}
36563694
}
36573695

36583696
/*

src/backend/executor/execParallel.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,9 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate,
10761076
case T_MemoizeState:
10771077
ExecMemoizeRetrieveInstrumentation((MemoizeState *) planstate);
10781078
break;
1079+
case T_BitmapHeapScanState:
1080+
ExecBitmapHeapRetrieveInstrumentation((BitmapHeapScanState *) planstate);
1081+
break;
10791082
default:
10801083
break;
10811084
}

src/backend/executor/nodeBitmapHeapscan.c

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,9 @@ BitmapHeapNext(BitmapHeapScanState *node)
236236
valid_block = table_scan_bitmap_next_block(scan, tbmres);
237237

238238
if (tbmres->ntuples >= 0)
239-
node->exact_pages++;
239+
node->stats.exact_pages++;
240240
else
241-
node->lossy_pages++;
241+
node->stats.lossy_pages++;
242242

243243
if (!valid_block)
244244
{
@@ -627,6 +627,29 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
627627
{
628628
TableScanDesc scanDesc;
629629

630+
/*
631+
* When ending a parallel worker, copy the statistics gathered by the
632+
* worker back into shared memory so that it can be picked up by the main
633+
* process to report in EXPLAIN ANALYZE.
634+
*/
635+
if (node->sinstrument != NULL && IsParallelWorker())
636+
{
637+
BitmapHeapScanInstrumentation *si;
638+
639+
Assert(ParallelWorkerNumber <= node->sinstrument->num_workers);
640+
si = &node->sinstrument->sinstrument[ParallelWorkerNumber];
641+
642+
/*
643+
* Here we accumulate the stats rather than performing memcpy on
644+
* node->stats into si. When a Gather/GatherMerge node finishes it
645+
* will perform planner shutdown on the workers. On rescan it will
646+
* spin up new workers which will have a new BitmapHeapScanState and
647+
* zeroed stats.
648+
*/
649+
si->exact_pages += node->stats.exact_pages;
650+
si->lossy_pages += node->stats.lossy_pages;
651+
}
652+
630653
/*
631654
* extract information from the node
632655
*/
@@ -694,8 +717,10 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
694717
scanstate->tbmiterator = NULL;
695718
scanstate->tbmres = NULL;
696719
scanstate->pvmbuffer = InvalidBuffer;
697-
scanstate->exact_pages = 0;
698-
scanstate->lossy_pages = 0;
720+
721+
/* Zero the statistics counters */
722+
memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
723+
699724
scanstate->prefetch_iterator = NULL;
700725
scanstate->prefetch_pages = 0;
701726
scanstate->prefetch_target = 0;
@@ -803,7 +828,18 @@ void
803828
ExecBitmapHeapEstimate(BitmapHeapScanState *node,
804829
ParallelContext *pcxt)
805830
{
806-
shm_toc_estimate_chunk(&pcxt->estimator, sizeof(ParallelBitmapHeapState));
831+
Size size;
832+
833+
size = MAXALIGN(sizeof(ParallelBitmapHeapState));
834+
835+
/* account for instrumentation, if required */
836+
if (node->ss.ps.instrument && pcxt->nworkers > 0)
837+
{
838+
size = add_size(size, offsetof(SharedBitmapHeapInstrumentation, sinstrument));
839+
size = add_size(size, mul_size(pcxt->nworkers, sizeof(BitmapHeapScanInstrumentation)));
840+
}
841+
842+
shm_toc_estimate_chunk(&pcxt->estimator, size);
807843
shm_toc_estimate_keys(&pcxt->estimator, 1);
808844
}
809845

@@ -818,13 +854,27 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
818854
ParallelContext *pcxt)
819855
{
820856
ParallelBitmapHeapState *pstate;
857+
SharedBitmapHeapInstrumentation *sinstrument = NULL;
821858
dsa_area *dsa = node->ss.ps.state->es_query_dsa;
859+
char *ptr;
860+
Size size;
822861

823862
/* If there's no DSA, there are no workers; initialize nothing. */
824863
if (dsa == NULL)
825864
return;
826865

827-
pstate = shm_toc_allocate(pcxt->toc, sizeof(ParallelBitmapHeapState));
866+
size = MAXALIGN(sizeof(ParallelBitmapHeapState));
867+
if (node->ss.ps.instrument && pcxt->nworkers > 0)
868+
{
869+
size = add_size(size, offsetof(SharedBitmapHeapInstrumentation, sinstrument));
870+
size = add_size(size, mul_size(pcxt->nworkers, sizeof(BitmapHeapScanInstrumentation)));
871+
}
872+
873+
ptr = shm_toc_allocate(pcxt->toc, size);
874+
pstate = (ParallelBitmapHeapState *) ptr;
875+
ptr += MAXALIGN(sizeof(ParallelBitmapHeapState));
876+
if (node->ss.ps.instrument && pcxt->nworkers > 0)
877+
sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
828878

829879
pstate->tbmiterator = 0;
830880
pstate->prefetch_iterator = 0;
@@ -837,8 +887,18 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
837887

838888
ConditionVariableInit(&pstate->cv);
839889

890+
if (sinstrument)
891+
{
892+
sinstrument->num_workers = pcxt->nworkers;
893+
894+
/* ensure any unfilled slots will contain zeroes */
895+
memset(sinstrument->sinstrument, 0,
896+
pcxt->nworkers * sizeof(BitmapHeapScanInstrumentation));
897+
}
898+
840899
shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
841900
node->pstate = pstate;
901+
node->sinstrument = sinstrument;
842902
}
843903

844904
/* ----------------------------------------------------------------
@@ -880,10 +940,37 @@ void
880940
ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
881941
ParallelWorkerContext *pwcxt)
882942
{
883-
ParallelBitmapHeapState *pstate;
943+
char *ptr;
884944

885945
Assert(node->ss.ps.state->es_query_dsa != NULL);
886946

887-
pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
888-
node->pstate = pstate;
947+
ptr = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
948+
949+
node->pstate = (ParallelBitmapHeapState *) ptr;
950+
ptr += MAXALIGN(sizeof(ParallelBitmapHeapState));
951+
952+
if (node->ss.ps.instrument)
953+
node->sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
954+
}
955+
956+
/* ----------------------------------------------------------------
957+
* ExecBitmapHeapRetrieveInstrumentation
958+
*
959+
* Transfer bitmap heap scan statistics from DSM to private memory.
960+
* ----------------------------------------------------------------
961+
*/
962+
void
963+
ExecBitmapHeapRetrieveInstrumentation(BitmapHeapScanState *node)
964+
{
965+
SharedBitmapHeapInstrumentation *sinstrument = node->sinstrument;
966+
Size size;
967+
968+
if (sinstrument == NULL)
969+
return;
970+
971+
size = offsetof(SharedBitmapHeapInstrumentation, sinstrument)
972+
+ sinstrument->num_workers * sizeof(BitmapHeapScanInstrumentation);
973+
974+
node->sinstrument = palloc(size);
975+
memcpy(node->sinstrument, sinstrument, size);
889976
}

src/include/executor/nodeBitmapHeapscan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
2828
ParallelContext *pcxt);
2929
extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
3030
ParallelWorkerContext *pwcxt);
31+
extern void ExecBitmapHeapRetrieveInstrumentation(BitmapHeapScanState *node);
3132

3233
#endif /* NODEBITMAPHEAPSCAN_H */

src/include/nodes/execnodes.h

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,19 @@ typedef struct BitmapIndexScanState
17461746
struct IndexScanDescData *biss_ScanDesc;
17471747
} BitmapIndexScanState;
17481748

1749+
/* ----------------
1750+
* BitmapHeapScanInstrumentation information
1751+
*
1752+
* exact_pages total number of exact pages retrieved
1753+
* lossy_pages total number of lossy pages retrieved
1754+
* ----------------
1755+
*/
1756+
typedef struct BitmapHeapScanInstrumentation
1757+
{
1758+
uint64 exact_pages;
1759+
uint64 lossy_pages;
1760+
} BitmapHeapScanInstrumentation;
1761+
17491762
/* ----------------
17501763
* SharedBitmapState information
17511764
*
@@ -1789,6 +1802,20 @@ typedef struct ParallelBitmapHeapState
17891802
ConditionVariable cv;
17901803
} ParallelBitmapHeapState;
17911804

1805+
/* ----------------
1806+
* Instrumentation data for a parallel bitmap heap scan.
1807+
*
1808+
* A shared memory struct that each parallel worker copies its
1809+
* BitmapHeapScanInstrumentation information into at executor shutdown to
1810+
* allow the leader to display the information in EXPLAIN ANALYZE.
1811+
* ----------------
1812+
*/
1813+
typedef struct SharedBitmapHeapInstrumentation
1814+
{
1815+
int num_workers;
1816+
BitmapHeapScanInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
1817+
} SharedBitmapHeapInstrumentation;
1818+
17921819
/* ----------------
17931820
* BitmapHeapScanState information
17941821
*
@@ -1797,8 +1824,7 @@ typedef struct ParallelBitmapHeapState
17971824
* tbmiterator iterator for scanning current pages
17981825
* tbmres current-page data
17991826
* pvmbuffer buffer for visibility-map lookups of prefetched pages
1800-
* exact_pages total number of exact pages retrieved
1801-
* lossy_pages total number of lossy pages retrieved
1827+
* stats execution statistics
18021828
* prefetch_iterator iterator for prefetching ahead of current page
18031829
* prefetch_pages # pages prefetch iterator is ahead of current
18041830
* prefetch_target current target prefetch distance
@@ -1807,6 +1833,7 @@ typedef struct ParallelBitmapHeapState
18071833
* shared_tbmiterator shared iterator
18081834
* shared_prefetch_iterator shared iterator for prefetching
18091835
* pstate shared state for parallel bitmap scan
1836+
* sinstrument statistics for parallel workers
18101837
* ----------------
18111838
*/
18121839
typedef struct BitmapHeapScanState
@@ -1817,8 +1844,7 @@ typedef struct BitmapHeapScanState
18171844
TBMIterator *tbmiterator;
18181845
TBMIterateResult *tbmres;
18191846
Buffer pvmbuffer;
1820-
uint64 exact_pages;
1821-
uint64 lossy_pages;
1847+
BitmapHeapScanInstrumentation stats;
18221848
TBMIterator *prefetch_iterator;
18231849
int prefetch_pages;
18241850
int prefetch_target;
@@ -1827,6 +1853,7 @@ typedef struct BitmapHeapScanState
18271853
TBMSharedIterator *shared_tbmiterator;
18281854
TBMSharedIterator *shared_prefetch_iterator;
18291855
ParallelBitmapHeapState *pstate;
1856+
SharedBitmapHeapInstrumentation *sinstrument;
18301857
} BitmapHeapScanState;
18311858

18321859
/* ----------------

src/tools/pgindent/typedefs.list

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ BitmapAndPath
262262
BitmapAndState
263263
BitmapHeapPath
264264
BitmapHeapScan
265+
BitmapHeapScanInstrumentation
265266
BitmapHeapScanState
266267
BitmapIndexScan
267268
BitmapIndexScanState
@@ -2603,6 +2604,7 @@ SetToDefault
26032604
SetupWorkerPtrType
26042605
ShDependObjectInfo
26052606
SharedAggInfo
2607+
SharedBitmapHeapInstrumentation
26062608
SharedBitmapState
26072609
SharedDependencyObjectType
26082610
SharedDependencyType

0 commit comments

Comments
 (0)