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/
20200301083601.ews6hz5dduc3w2se@alap3.anarazel.de
* crash/basebackup, even though the state of the data directory would
* require it.
*/
- Assert(!MyPgXact->delayChkpt);
- MyPgXact->delayChkpt = true;
+ Assert(!MyProc->delayChkpt);
+ MyProc->delayChkpt = true;
/* WAL log truncation */
WriteMTruncateXlogRec(newOldestMultiDB,
/* Then offsets */
PerformOffsetsTruncation(oldestMulti, newOldestMulti);
- MyPgXact->delayChkpt = false;
+ MyProc->delayChkpt = false;
END_CRIT_SECTION();
LWLockRelease(MultiXactTruncationLock);
proc->lxid = (LocalTransactionId) xid;
pgxact->xid = xid;
pgxact->xmin = InvalidTransactionId;
- pgxact->delayChkpt = false;
+ proc->delayChkpt = false;
pgxact->vacuumFlags = 0;
proc->pid = 0;
proc->backendId = InvalidBackendId;
START_CRIT_SECTION();
- MyPgXact->delayChkpt = true;
+ MyProc->delayChkpt = true;
XLogBeginInsert();
for (record = records.head; record != NULL; record = record->next)
* checkpoint starting after this will certainly see the gxact as a
* candidate for fsyncing.
*/
- MyPgXact->delayChkpt = false;
+ MyProc->delayChkpt = false;
/*
* Remember that we have this GlobalTransaction entry locked for us. If
START_CRIT_SECTION();
/* See notes in RecordTransactionCommit */
- MyPgXact->delayChkpt = true;
+ MyProc->delayChkpt = true;
/*
* Emit the XLOG commit record. Note that we mark 2PC commits as
TransactionIdCommitTree(xid, nchildren, children);
/* Checkpoint can proceed now */
- MyPgXact->delayChkpt = false;
+ MyProc->delayChkpt = false;
END_CRIT_SECTION();
* a bit fuzzy, but it doesn't matter.
*/
START_CRIT_SECTION();
- MyPgXact->delayChkpt = true;
+ MyProc->delayChkpt = true;
SetCurrentTransactionStopTimestamp();
*/
if (markXidCommitted)
{
- MyPgXact->delayChkpt = false;
+ MyProc->delayChkpt = false;
END_CRIT_SECTION();
}
/*
* Ensure no checkpoint can change our view of RedoRecPtr.
*/
- Assert(MyPgXact->delayChkpt);
+ Assert(MyProc->delayChkpt);
/*
* Update RedoRecPtr so that we can make the right decision
* essential that CreateCheckpoint waits for virtual transactions
* rather than full transactionids.
*/
- MyPgXact->delayChkpt = delayChkpt = true;
+ MyProc->delayChkpt = delayChkpt = true;
lsn = XLogSaveBufferForHint(buffer, buffer_std);
}
UnlockBufHdr(bufHdr, buf_state);
if (delayChkpt)
- MyPgXact->delayChkpt = false;
+ MyProc->delayChkpt = false;
if (dirtied)
{
pgxact->xmin = InvalidTransactionId;
/* must be cleared with xid/xmin: */
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
- pgxact->delayChkpt = false; /* be sure this is cleared in abort */
+ proc->delayChkpt = false; /* be sure this is cleared in abort */
proc->recoveryConflictPending = false;
Assert(pgxact->nxids == 0);
pgxact->xmin = InvalidTransactionId;
/* must be cleared with xid/xmin: */
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
- pgxact->delayChkpt = false; /* be sure this is cleared in abort */
+ proc->delayChkpt = false; /* be sure this is cleared in abort */
proc->recoveryConflictPending = false;
/* Clear the subtransaction-XID cache too while holding the lock */
/* redundant, but just in case */
pgxact->vacuumFlags &= ~PROC_VACUUM_STATE_MASK;
- pgxact->delayChkpt = false;
+ proc->delayChkpt = false;
/* Clear the subtransaction-XID cache too */
pgxact->nxids = 0;
* delaying checkpoint because they have critical actions in progress.
*
* Constructs an array of VXIDs of transactions that are currently in commit
- * critical sections, as shown by having delayChkpt set in their PGXACT.
+ * critical sections, as shown by having delayChkpt set in their PGPROC.
*
* Returns a palloc'd array that should be freed by the caller.
* *nvxids is the number of valid entries.
{
int pgprocno = arrayP->pgprocnos[index];
PGPROC *proc = &allProcs[pgprocno];
- PGXACT *pgxact = &allPgXact[pgprocno];
- if (pgxact->delayChkpt)
+ if (proc->delayChkpt)
{
VirtualTransactionId vxid;
{
int pgprocno = arrayP->pgprocnos[index];
PGPROC *proc = &allProcs[pgprocno];
- PGXACT *pgxact = &allPgXact[pgprocno];
VirtualTransactionId vxid;
GET_VXID_FROM_PGPROC(vxid, *proc);
- if (pgxact->delayChkpt && VirtualTransactionIdIsValid(vxid))
+ if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
{
int i;
MyProc->roleId = InvalidOid;
MyProc->tempNamespaceId = InvalidOid;
MyProc->isBackgroundWorker = IsBackgroundWorker;
- MyPgXact->delayChkpt = false;
+ MyProc->delayChkpt = false;
MyPgXact->vacuumFlags = 0;
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
if (IsAutoVacuumWorkerProcess())
MyProc->roleId = InvalidOid;
MyProc->tempNamespaceId = InvalidOid;
MyProc->isBackgroundWorker = IsBackgroundWorker;
- MyPgXact->delayChkpt = false;
+ MyProc->delayChkpt = false;
MyPgXact->vacuumFlags = 0;
MyProc->lwWaiting = false;
MyProc->lwWaitMode = 0;
LOCKMASK heldLocks; /* bitmask for lock types already held on this
* lock object by this backend */
+ bool delayChkpt; /* true if this proc delays checkpoint start */
+
/*
* Info to allow us to wait for synchronous replication, if needed.
* waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend.
uint8 vacuumFlags; /* vacuum-related flags, see above */
bool overflowed;
- bool delayChkpt; /* true if this proc delays checkpoint start;
- * previously called InCommit */
uint8 nxids;
} PGXACT;