64
64
#include "access/xlog.h"
65
65
#include "access/xloginsert.h"
66
66
#include "catalog/index.h"
67
+ #include "executor/instrument.h"
67
68
#include "miscadmin.h"
68
69
#include "pgstat.h"
69
70
#include "storage/smgr.h"
78
79
#define PARALLEL_KEY_TUPLESORT UINT64CONST(0xA000000000000002)
79
80
#define PARALLEL_KEY_TUPLESORT_SPOOL2 UINT64CONST(0xA000000000000003)
80
81
#define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xA000000000000004)
82
+ #define PARALLEL_KEY_BUFFER_USAGE UINT64CONST(0xA000000000000005)
81
83
82
84
/*
83
85
* DISABLE_LEADER_PARTICIPATION disables the leader's participation in
@@ -192,6 +194,7 @@ typedef struct BTLeader
192
194
Sharedsort * sharedsort ;
193
195
Sharedsort * sharedsort2 ;
194
196
Snapshot snapshot ;
197
+ BufferUsage * bufferusage ;
195
198
}BTLeader ;
196
199
197
200
/*
@@ -1240,6 +1243,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
1240
1243
Sharedsort * sharedsort2 ;
1241
1244
BTSpool * btspool = buildstate -> spool ;
1242
1245
BTLeader * btleader = (BTLeader * )palloc0 (sizeof (BTLeader ));
1246
+ BufferUsage * bufferusage ;
1243
1247
bool leaderparticipates = true;
1244
1248
char * sharedquery ;
1245
1249
int querylen ;
@@ -1292,6 +1296,17 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
1292
1296
shm_toc_estimate_keys (& pcxt -> estimator ,3 );
1293
1297
}
1294
1298
1299
+ /*
1300
+ * Estimate space for BufferUsage -- PARALLEL_KEY_BUFFER_USAGE.
1301
+ *
1302
+ * If there are no extensions loaded that care, we could skip this. We
1303
+ * have no way of knowing whether anyone's looking at pgBufferUsage, so do
1304
+ * it unconditionally.
1305
+ */
1306
+ shm_toc_estimate_chunk (& pcxt -> estimator ,
1307
+ mul_size (sizeof (BufferUsage ),pcxt -> nworkers ));
1308
+ shm_toc_estimate_keys (& pcxt -> estimator ,1 );
1309
+
1295
1310
/* Finally, estimate PARALLEL_KEY_QUERY_TEXT space */
1296
1311
querylen = strlen (debug_query_string );
1297
1312
shm_toc_estimate_chunk (& pcxt -> estimator ,querylen + 1 );
@@ -1361,6 +1376,11 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
1361
1376
memcpy (sharedquery ,debug_query_string ,querylen + 1 );
1362
1377
shm_toc_insert (pcxt -> toc ,PARALLEL_KEY_QUERY_TEXT ,sharedquery );
1363
1378
1379
+ /* Allocate space for each worker's BufferUsage; no need to initialize */
1380
+ bufferusage = shm_toc_allocate (pcxt -> toc ,
1381
+ mul_size (sizeof (BufferUsage ),pcxt -> nworkers ));
1382
+ shm_toc_insert (pcxt -> toc ,PARALLEL_KEY_BUFFER_USAGE ,bufferusage );
1383
+
1364
1384
/* Launch workers, saving status for leader/caller */
1365
1385
LaunchParallelWorkers (pcxt );
1366
1386
btleader -> pcxt = pcxt ;
@@ -1371,6 +1391,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
1371
1391
btleader -> sharedsort = sharedsort ;
1372
1392
btleader -> sharedsort2 = sharedsort2 ;
1373
1393
btleader -> snapshot = snapshot ;
1394
+ btleader -> bufferusage = bufferusage ;
1374
1395
1375
1396
/* If no workers were successfully launched, back out (do serial build) */
1376
1397
if (pcxt -> nworkers_launched == 0 )
@@ -1399,8 +1420,18 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
1399
1420
static void
1400
1421
_bt_end_parallel (BTLeader * btleader )
1401
1422
{
1423
+ int i ;
1424
+
1402
1425
/* Shutdown worker processes */
1403
1426
WaitForParallelWorkersToFinish (btleader -> pcxt );
1427
+
1428
+ /*
1429
+ * Next, accumulate buffer usage. (This must wait for the workers to
1430
+ * finish, or we might get incomplete data.)
1431
+ */
1432
+ for (i = 0 ;i < btleader -> pcxt -> nworkers_launched ;i ++ )
1433
+ InstrAccumParallelQuery (& btleader -> bufferusage [i ]);
1434
+
1404
1435
/* Free last reference to MVCC snapshot, if one was used */
1405
1436
if (IsMVCCSnapshot (btleader -> snapshot ))
1406
1437
UnregisterSnapshot (btleader -> snapshot );
@@ -1537,6 +1568,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
1537
1568
Relation indexRel ;
1538
1569
LOCKMODE heapLockmode ;
1539
1570
LOCKMODE indexLockmode ;
1571
+ BufferUsage * bufferusage ;
1540
1572
int sortmem ;
1541
1573
1542
1574
#ifdef BTREE_BUILD_STATS
@@ -1598,11 +1630,18 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
1598
1630
tuplesort_attach_shared (sharedsort2 ,seg );
1599
1631
}
1600
1632
1633
+ /* Prepare to track buffer usage during parallel execution */
1634
+ InstrStartParallelQuery ();
1635
+
1601
1636
/* Perform sorting of spool, and possibly a spool2 */
1602
1637
sortmem = maintenance_work_mem /btshared -> scantuplesortstates ;
1603
1638
_bt_parallel_scan_and_sort (btspool ,btspool2 ,btshared ,sharedsort ,
1604
1639
sharedsort2 ,sortmem );
1605
1640
1641
+ /* Report buffer usage during parallel execution */
1642
+ bufferusage = shm_toc_lookup (toc ,PARALLEL_KEY_BUFFER_USAGE , false);
1643
+ InstrEndParallelQuery (& bufferusage [ParallelWorkerNumber ]);
1644
+
1606
1645
#ifdef BTREE_BUILD_STATS
1607
1646
if (log_btree_build_stats )
1608
1647
{