6767#include "access/xloginsert.h"
6868#include "catalog/index.h"
6969#include "commands/progress.h"
70+ #include "executor/instrument.h"
7071#include "miscadmin.h"
7172#include "pgstat.h"
7273#include "storage/smgr.h"
8182#define PARALLEL_KEY_TUPLESORT UINT64CONST(0xA000000000000002)
8283#define PARALLEL_KEY_TUPLESORT_SPOOL2 UINT64CONST(0xA000000000000003)
8384#define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xA000000000000004)
85+ #define PARALLEL_KEY_BUFFER_USAGE UINT64CONST(0xA000000000000005)
8486
8587/*
8688 * DISABLE_LEADER_PARTICIPATION disables the leader's participation in
@@ -203,6 +205,7 @@ typedef struct BTLeader
203205Sharedsort * sharedsort ;
204206Sharedsort * sharedsort2 ;
205207Snapshot snapshot ;
208+ BufferUsage * bufferusage ;
206209}BTLeader ;
207210
208211/*
@@ -1336,6 +1339,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
13361339Sharedsort * sharedsort2 ;
13371340BTSpool * btspool = buildstate -> spool ;
13381341BTLeader * btleader = (BTLeader * )palloc0 (sizeof (BTLeader ));
1342+ BufferUsage * bufferusage ;
13391343bool leaderparticipates = true;
13401344char * sharedquery ;
13411345int querylen ;
@@ -1388,6 +1392,17 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
13881392shm_toc_estimate_keys (& pcxt -> estimator ,3 );
13891393}
13901394
1395+ /*
1396+ * Estimate space for BufferUsage -- PARALLEL_KEY_BUFFER_USAGE.
1397+ *
1398+ * If there are no extensions loaded that care, we could skip this. We
1399+ * have no way of knowing whether anyone's looking at pgBufferUsage, so do
1400+ * it unconditionally.
1401+ */
1402+ shm_toc_estimate_chunk (& pcxt -> estimator ,
1403+ mul_size (sizeof (BufferUsage ),pcxt -> nworkers ));
1404+ shm_toc_estimate_keys (& pcxt -> estimator ,1 );
1405+
13911406/* Finally, estimate PARALLEL_KEY_QUERY_TEXT space */
13921407querylen = strlen (debug_query_string );
13931408shm_toc_estimate_chunk (& pcxt -> estimator ,querylen + 1 );
@@ -1459,6 +1474,11 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
14591474memcpy (sharedquery ,debug_query_string ,querylen + 1 );
14601475shm_toc_insert (pcxt -> toc ,PARALLEL_KEY_QUERY_TEXT ,sharedquery );
14611476
1477+ /* Allocate space for each worker's BufferUsage; no need to initialize */
1478+ bufferusage = shm_toc_allocate (pcxt -> toc ,
1479+ mul_size (sizeof (BufferUsage ),pcxt -> nworkers ));
1480+ shm_toc_insert (pcxt -> toc ,PARALLEL_KEY_BUFFER_USAGE ,bufferusage );
1481+
14621482/* Launch workers, saving status for leader/caller */
14631483LaunchParallelWorkers (pcxt );
14641484btleader -> pcxt = pcxt ;
@@ -1469,6 +1489,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
14691489btleader -> sharedsort = sharedsort ;
14701490btleader -> sharedsort2 = sharedsort2 ;
14711491btleader -> snapshot = snapshot ;
1492+ btleader -> bufferusage = bufferusage ;
14721493
14731494/* If no workers were successfully launched, back out (do serial build) */
14741495if (pcxt -> nworkers_launched == 0 )
@@ -1497,8 +1518,18 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
14971518static void
14981519_bt_end_parallel (BTLeader * btleader )
14991520{
1521+ int i ;
1522+
15001523/* Shutdown worker processes */
15011524WaitForParallelWorkersToFinish (btleader -> pcxt );
1525+
1526+ /*
1527+ * Next, accumulate buffer usage. (This must wait for the workers to
1528+ * finish, or we might get incomplete data.)
1529+ */
1530+ for (i = 0 ;i < btleader -> pcxt -> nworkers_launched ;i ++ )
1531+ InstrAccumParallelQuery (& btleader -> bufferusage [i ]);
1532+
15021533/* Free last reference to MVCC snapshot, if one was used */
15031534if (IsMVCCSnapshot (btleader -> snapshot ))
15041535UnregisterSnapshot (btleader -> snapshot );
@@ -1629,6 +1660,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
16291660Relation indexRel ;
16301661LOCKMODE heapLockmode ;
16311662LOCKMODE indexLockmode ;
1663+ BufferUsage * bufferusage ;
16321664int sortmem ;
16331665
16341666#ifdef BTREE_BUILD_STATS
@@ -1690,11 +1722,18 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
16901722tuplesort_attach_shared (sharedsort2 ,seg );
16911723}
16921724
1725+ /* Prepare to track buffer usage during parallel execution */
1726+ InstrStartParallelQuery ();
1727+
16931728/* Perform sorting of spool, and possibly a spool2 */
16941729sortmem = maintenance_work_mem /btshared -> scantuplesortstates ;
16951730_bt_parallel_scan_and_sort (btspool ,btspool2 ,btshared ,sharedsort ,
16961731sharedsort2 ,sortmem , false);
16971732
1733+ /* Report buffer usage during parallel execution */
1734+ bufferusage = shm_toc_lookup (toc ,PARALLEL_KEY_BUFFER_USAGE , false);
1735+ InstrEndParallelQuery (& bufferusage [ParallelWorkerNumber ]);
1736+
16981737#ifdef BTREE_BUILD_STATS
16991738if (log_btree_build_stats )
17001739{