Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7e3da1c

Browse files
committed
Mitigate "snapshot too old" performance regression on NUMA
Limit maintenance of time to xid mapping to once per minute. Atleast in the tested case this brings performance within 5% of whenthe feature is off, compared to several times slower without thispatch.While there, fix comments and whitespace.Ants Aasma, with cosmetic adjustments suggested by Andres FreundReviewed by Kevin Grittner and Andres Freund
1 parenteb7de00 commit7e3da1c

File tree

1 file changed

+62
-23
lines changed

1 file changed

+62
-23
lines changed

‎src/backend/utils/time/snapmgr.c

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,13 @@ typedef struct OldSnapshotControlData
7878
* Variables for old snapshot handling are shared among processes and are
7979
* only allowed to move forward.
8080
*/
81-
slock_tmutex_current;/* protectcurrent timestamp */
81+
slock_tmutex_current;/* protectcurrent_timestamp */
8282
int64current_timestamp;/* latest snapshot timestamp */
83-
slock_tmutex_latest_xmin;/* protect latest snapshot xmin */
83+
slock_tmutex_latest_xmin;/* protect latest_xmin
84+
* and next_map_update
85+
*/
8486
TransactionIdlatest_xmin;/* latest snapshot xmin */
87+
int64next_map_update;/* latest snapshot valid up to */
8588
slock_tmutex_threshold;/* protect threshold fields */
8689
int64threshold_timestamp;/* earlier snapshot is old */
8790
TransactionIdthreshold_xid;/* earlier xid may be gone */
@@ -95,7 +98,10 @@ typedef struct OldSnapshotControlData
9598
* count_used value of OLD_SNAPSHOT_TIME_MAP_ENTRIES means that the buffer
9699
* is full and the head must be advanced to add new entries. Use
97100
* timestamps aligned to minute boundaries, since that seems less
98-
* surprising than aligning based on the first usage timestamp.
101+
* surprising than aligning based on the first usage timestamp. The
102+
* latest bucket is effectively stored within latest_xmin. The circular
103+
* buffer is updated when we get a new xmin value that doesn't fall into
104+
* the same interval.
99105
*
100106
* It is OK if the xid for a given time slot is from earlier than
101107
* calculated by adding the number of minutes corresponding to the
@@ -269,6 +275,7 @@ SnapMgrInit(void)
269275
oldSnapshotControl->current_timestamp=0;
270276
SpinLockInit(&oldSnapshotControl->mutex_latest_xmin);
271277
oldSnapshotControl->latest_xmin=InvalidTransactionId;
278+
oldSnapshotControl->next_map_update=0;
272279
SpinLockInit(&oldSnapshotControl->mutex_threshold);
273280
oldSnapshotControl->threshold_timestamp=0;
274281
oldSnapshotControl->threshold_xid=InvalidTransactionId;
@@ -1595,9 +1602,15 @@ TransactionIdLimitedForOldSnapshots(TransactionId recentXmin,
15951602
{
15961603
int64ts=GetSnapshotCurrentTimestamp();
15971604
TransactionIdxlimit=recentXmin;
1598-
TransactionIdlatest_xmin=oldSnapshotControl->latest_xmin;
1605+
TransactionIdlatest_xmin;
1606+
int64update_ts;
15991607
boolsame_ts_as_threshold= false;
16001608

1609+
SpinLockAcquire(&oldSnapshotControl->mutex_latest_xmin);
1610+
latest_xmin=oldSnapshotControl->latest_xmin;
1611+
update_ts=oldSnapshotControl->next_map_update;
1612+
SpinLockRelease(&oldSnapshotControl->mutex_latest_xmin);
1613+
16011614
/*
16021615
* Zero threshold always overrides to latest xmin, if valid. Without
16031616
* some heuristic it will find its own snapshot too old on, for
@@ -1632,26 +1645,35 @@ TransactionIdLimitedForOldSnapshots(TransactionId recentXmin,
16321645

16331646
if (!same_ts_as_threshold)
16341647
{
1635-
LWLockAcquire(OldSnapshotTimeMapLock,LW_SHARED);
1636-
1637-
if (oldSnapshotControl->count_used>0
1638-
&&ts >=oldSnapshotControl->head_timestamp)
1648+
if (ts==update_ts)
16391649
{
1640-
intoffset;
1641-
1642-
offset= ((ts-oldSnapshotControl->head_timestamp)
1643-
/USECS_PER_MINUTE);
1644-
if (offset>oldSnapshotControl->count_used-1)
1645-
offset=oldSnapshotControl->count_used-1;
1646-
offset= (oldSnapshotControl->head_offset+offset)
1647-
%OLD_SNAPSHOT_TIME_MAP_ENTRIES;
1648-
xlimit=oldSnapshotControl->xid_by_minute[offset];
1649-
1650+
xlimit=latest_xmin;
16501651
if (NormalTransactionIdFollows(xlimit,recentXmin))
16511652
SetOldSnapshotThresholdTimestamp(ts,xlimit);
16521653
}
1654+
else
1655+
{
1656+
LWLockAcquire(OldSnapshotTimeMapLock,LW_SHARED);
16531657

1654-
LWLockRelease(OldSnapshotTimeMapLock);
1658+
if (oldSnapshotControl->count_used>0
1659+
&&ts >=oldSnapshotControl->head_timestamp)
1660+
{
1661+
intoffset;
1662+
1663+
offset= ((ts-oldSnapshotControl->head_timestamp)
1664+
/USECS_PER_MINUTE);
1665+
if (offset>oldSnapshotControl->count_used-1)
1666+
offset=oldSnapshotControl->count_used-1;
1667+
offset= (oldSnapshotControl->head_offset+offset)
1668+
%OLD_SNAPSHOT_TIME_MAP_ENTRIES;
1669+
xlimit=oldSnapshotControl->xid_by_minute[offset];
1670+
1671+
if (NormalTransactionIdFollows(xlimit,recentXmin))
1672+
SetOldSnapshotThresholdTimestamp(ts,xlimit);
1673+
}
1674+
1675+
LWLockRelease(OldSnapshotTimeMapLock);
1676+
}
16551677
}
16561678

16571679
/*
@@ -1681,16 +1703,35 @@ void
16811703
MaintainOldSnapshotTimeMapping(int64whenTaken,TransactionIdxmin)
16821704
{
16831705
int64ts;
1706+
TransactionIdlatest_xmin;
1707+
int64update_ts;
1708+
boolmap_update_required= false;
16841709

16851710
/* Never call this function when old snapshot checking is disabled. */
16861711
Assert(old_snapshot_threshold >=0);
16871712

1688-
/* Keep track of the latest xmin seen by any process. */
1713+
ts=AlignTimestampToMinuteBoundary(whenTaken);
1714+
1715+
/*
1716+
* Keep track of the latest xmin seen by any process. Update mapping
1717+
* with a new value when we have crossed a bucket boundary.
1718+
*/
16891719
SpinLockAcquire(&oldSnapshotControl->mutex_latest_xmin);
1690-
if (TransactionIdFollows(xmin,oldSnapshotControl->latest_xmin))
1720+
latest_xmin=oldSnapshotControl->latest_xmin;
1721+
update_ts=oldSnapshotControl->next_map_update;
1722+
if (ts>update_ts)
1723+
{
1724+
oldSnapshotControl->next_map_update=ts;
1725+
map_update_required= true;
1726+
}
1727+
if (TransactionIdFollows(xmin,latest_xmin))
16911728
oldSnapshotControl->latest_xmin=xmin;
16921729
SpinLockRelease(&oldSnapshotControl->mutex_latest_xmin);
16931730

1731+
/* We only needed to update the most recent xmin value. */
1732+
if (!map_update_required)
1733+
return;
1734+
16941735
/* No further tracking needed for 0 (used for testing). */
16951736
if (old_snapshot_threshold==0)
16961737
return;
@@ -1716,8 +1757,6 @@ MaintainOldSnapshotTimeMapping(int64 whenTaken, TransactionId xmin)
17161757
return;
17171758
}
17181759

1719-
ts=AlignTimestampToMinuteBoundary(whenTaken);
1720-
17211760
LWLockAcquire(OldSnapshotTimeMapLock,LW_EXCLUSIVE);
17221761

17231762
Assert(oldSnapshotControl->head_offset >=0);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp