Skip to content

Commit 75848bc

Browse files
committed
snapshot scalability: Move delayChkpt from PGXACT to PGPROC.
The goal of separating hotly accessed per-backend data from PGPROC into PGXACT is to make accesses fast (GetSnapshotData() in particular). But delayChkpt is not actually accessed frequently; only when starting a checkpoint. As it is frequently modified (multiple times in the course of a single transaction), storing it in the same cacheline as hotly accessed data unnecessarily dirties a contended cacheline. Therefore move delayChkpt to PGPROC. This is part of a larger series of patches intending to improve GetSnapshotData() scalability. It is committed and pushed separately, as it is independently beneficial (small but measurable win, limited by the other frequent modifications of PGXACT). Author: Andres Freund Reviewed-By: Robert Haas, Thomas Munro, David Rowley Discussion: https://postgr.es/m/[email protected]
1 parent 2b88fdd commit 75848bc

File tree

8 files changed

+23
-25
lines changed

8 files changed

+23
-25
lines changed

src/backend/access/transam/multixact.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -3058,8 +3058,8 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
30583058
* crash/basebackup, even though the state of the data directory would
30593059
* require it.
30603060
*/
3061-
Assert(!MyPgXact->delayChkpt);
3062-
MyPgXact->delayChkpt = true;
3061+
Assert(!MyProc->delayChkpt);
3062+
MyProc->delayChkpt = true;
30633063

30643064
/* WAL log truncation */
30653065
WriteMTruncateXlogRec(newOldestMultiDB,
@@ -3085,7 +3085,7 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
30853085
/* Then offsets */
30863086
PerformOffsetsTruncation(oldestMulti, newOldestMulti);
30873087

3088-
MyPgXact->delayChkpt = false;
3088+
MyProc->delayChkpt = false;
30893089

30903090
END_CRIT_SECTION();
30913091
LWLockRelease(MultiXactTruncationLock);

src/backend/access/transam/twophase.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
465465
proc->lxid = (LocalTransactionId) xid;
466466
pgxact->xid = xid;
467467
pgxact->xmin = InvalidTransactionId;
468-
pgxact->delayChkpt = false;
468+
proc->delayChkpt = false;
469469
pgxact->vacuumFlags = 0;
470470
proc->pid = 0;
471471
proc->backendId = InvalidBackendId;
@@ -1114,7 +1114,7 @@ EndPrepare(GlobalTransaction gxact)
11141114

11151115
START_CRIT_SECTION();
11161116

1117-
MyPgXact->delayChkpt = true;
1117+
MyProc->delayChkpt = true;
11181118

11191119
XLogBeginInsert();
11201120
for (record = records.head; record != NULL; record = record->next)
@@ -1157,7 +1157,7 @@ EndPrepare(GlobalTransaction gxact)
11571157
* checkpoint starting after this will certainly see the gxact as a
11581158
* candidate for fsyncing.
11591159
*/
1160-
MyPgXact->delayChkpt = false;
1160+
MyProc->delayChkpt = false;
11611161

11621162
/*
11631163
* Remember that we have this GlobalTransaction entry locked for us. If
@@ -2204,7 +2204,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
22042204
START_CRIT_SECTION();
22052205

22062206
/* See notes in RecordTransactionCommit */
2207-
MyPgXact->delayChkpt = true;
2207+
MyProc->delayChkpt = true;
22082208

22092209
/*
22102210
* Emit the XLOG commit record. Note that we mark 2PC commits as
@@ -2252,7 +2252,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
22522252
TransactionIdCommitTree(xid, nchildren, children);
22532253

22542254
/* Checkpoint can proceed now */
2255-
MyPgXact->delayChkpt = false;
2255+
MyProc->delayChkpt = false;
22562256

22572257
END_CRIT_SECTION();
22582258

src/backend/access/transam/xact.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ RecordTransactionCommit(void)
13071307
* a bit fuzzy, but it doesn't matter.
13081308
*/
13091309
START_CRIT_SECTION();
1310-
MyPgXact->delayChkpt = true;
1310+
MyProc->delayChkpt = true;
13111311

13121312
SetCurrentTransactionStopTimestamp();
13131313

@@ -1408,7 +1408,7 @@ RecordTransactionCommit(void)
14081408
*/
14091409
if (markXidCommitted)
14101410
{
1411-
MyPgXact->delayChkpt = false;
1411+
MyProc->delayChkpt = false;
14121412
END_CRIT_SECTION();
14131413
}
14141414

src/backend/access/transam/xloginsert.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ XLogSaveBufferForHint(Buffer buffer, bool buffer_std)
904904
/*
905905
* Ensure no checkpoint can change our view of RedoRecPtr.
906906
*/
907-
Assert(MyPgXact->delayChkpt);
907+
Assert(MyProc->delayChkpt);
908908

909909
/*
910910
* Update RedoRecPtr so that we can make the right decision

src/backend/storage/buffer/bufmgr.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -3587,7 +3587,7 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
35873587
* essential that CreateCheckpoint waits for virtual transactions
35883588
* rather than full transactionids.
35893589
*/
3590-
MyPgXact->delayChkpt = delayChkpt = true;
3590+
MyProc->delayChkpt = delayChkpt = true;
35913591
lsn = XLogSaveBufferForHint(buffer, buffer_std);
35923592
}
35933593

@@ -3620,7 +3620,7 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
36203620
UnlockBufHdr(bufHdr, buf_state);
36213621

36223622
if (delayChkpt)
3623-
MyPgXact->delayChkpt = false;
3623+
MyProc->delayChkpt = false;
36243624

36253625
if (dirtied)
36263626
{

src/backend/storage/ipc/procarray.c

+6-8
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
436436
pgxact->xmin = InvalidTransactionId;
437437
/* must be cleared with xid/xmin: */
438438
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
439-
pgxact->delayChkpt = false; /* be sure this is cleared in abort */
439+
proc->delayChkpt = false; /* be sure this is cleared in abort */
440440
proc->recoveryConflictPending = false;
441441

442442
Assert(pgxact->nxids == 0);
@@ -458,7 +458,7 @@ ProcArrayEndTransactionInternal(PGPROC *proc, PGXACT *pgxact,
458458
pgxact->xmin = InvalidTransactionId;
459459
/* must be cleared with xid/xmin: */
460460
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
461-
pgxact->delayChkpt = false; /* be sure this is cleared in abort */
461+
proc->delayChkpt = false; /* be sure this is cleared in abort */
462462
proc->recoveryConflictPending = false;
463463

464464
/* Clear the subtransaction-XID cache too while holding the lock */
@@ -616,7 +616,7 @@ ProcArrayClearTransaction(PGPROC *proc)
616616

617617
/* redundant, but just in case */
618618
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
619-
pgxact->delayChkpt = false;
619+
proc->delayChkpt = false;
620620

621621
/* Clear the subtransaction-XID cache too */
622622
pgxact->nxids = 0;
@@ -2257,7 +2257,7 @@ GetOldestSafeDecodingTransactionId(bool catalogOnly)
22572257
* delaying checkpoint because they have critical actions in progress.
22582258
*
22592259
* Constructs an array of VXIDs of transactions that are currently in commit
2260-
* critical sections, as shown by having delayChkpt set in their PGXACT.
2260+
* critical sections, as shown by having delayChkpt set in their PGPROC.
22612261
*
22622262
* Returns a palloc'd array that should be freed by the caller.
22632263
* *nvxids is the number of valid entries.
@@ -2288,9 +2288,8 @@ GetVirtualXIDsDelayingChkpt(int *nvxids)
22882288
{
22892289
int pgprocno = arrayP->pgprocnos[index];
22902290
PGPROC *proc = &allProcs[pgprocno];
2291-
PGXACT *pgxact = &allPgXact[pgprocno];
22922291

2293-
if (pgxact->delayChkpt)
2292+
if (proc->delayChkpt)
22942293
{
22952294
VirtualTransactionId vxid;
22962295

@@ -2328,12 +2327,11 @@ HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids)
23282327
{
23292328
int pgprocno = arrayP->pgprocnos[index];
23302329
PGPROC *proc = &allProcs[pgprocno];
2331-
PGXACT *pgxact = &allPgXact[pgprocno];
23322330
VirtualTransactionId vxid;
23332331

23342332
GET_VXID_FROM_PGPROC(vxid, *proc);
23352333

2336-
if (pgxact->delayChkpt && VirtualTransactionIdIsValid(vxid))
2334+
if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
23372335
{
23382336
int i;
23392337

src/backend/storage/lmgr/proc.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ InitProcess(void)
397397
MyProc->roleId = InvalidOid;
398398
MyProc->tempNamespaceId = InvalidOid;
399399
MyProc->isBackgroundWorker = IsBackgroundWorker;
400-
MyPgXact->delayChkpt = false;
400+
MyProc->delayChkpt = false;
401401
MyPgXact->vacuumFlags = 0;
402402
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
403403
if (IsAutoVacuumWorkerProcess())
@@ -579,7 +579,7 @@ InitAuxiliaryProcess(void)
579579
MyProc->roleId = InvalidOid;
580580
MyProc->tempNamespaceId = InvalidOid;
581581
MyProc->isBackgroundWorker = IsBackgroundWorker;
582-
MyPgXact->delayChkpt = false;
582+
MyProc->delayChkpt = false;
583583
MyPgXact->vacuumFlags = 0;
584584
MyProc->lwWaiting = false;
585585
MyProc->lwWaitMode = 0;

src/include/storage/proc.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ struct PGPROC
142142
LOCKMASK heldLocks; /* bitmask for lock types already held on this
143143
* lock object by this backend */
144144

145+
bool delayChkpt; /* true if this proc delays checkpoint start */
146+
145147
/*
146148
* Info to allow us to wait for synchronous replication, if needed.
147149
* waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend.
@@ -232,8 +234,6 @@ typedef struct PGXACT
232234

233235
uint8 vacuumFlags; /* vacuum-related flags, see above */
234236
bool overflowed;
235-
bool delayChkpt; /* true if this proc delays checkpoint start;
236-
* previously called InCommit */
237237

238238
uint8 nxids;
239239
} PGXACT;

0 commit comments

Comments
 (0)