Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7714c63

Browse files
committed
Remove extra copies of LogwrtResult.
This simplifies the code a little bit. The new rule is that to update XLogCtl->LogwrtResult, you must hold both WALWriteLock and info_lck, whereas before we had two copies, one that was protected by WALWriteLock and another protected by info_lck. The code that updates them was already holding both locks, so merging the two is trivial. The third copy, XLogCtl->Insert.LogwrtResult, was not totally redundant, it was used in AdvanceXLInsertBuffer to update the backend-local copy, before acquiring the info_lck to read the up-to-date value. But the value of that seems dubious; at best it's saving one spinlock acquisition per completed WAL page, which is not significant compared to all the other work involved. And in practice, it's probably not saving even that much.
1 parent 3b682df commit 7714c63

File tree

1 file changed

+22
-52
lines changed
  • src/backend/access/transam

1 file changed

+22
-52
lines changed

src/backend/access/transam/xlog.c

Lines changed: 22 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -289,35 +289,16 @@ static XLogRecPtr RedoStartLSN = {0, 0};
289289
* These structs are identical but are declared separately to indicate their
290290
* slightly different functions.
291291
*
292-
* We do a lot of pushups to minimize the amount of access to lockable
293-
* shared memory values. There are actually three shared-memory copies of
294-
* LogwrtResult, plus one unshared copy in each backend. Here's how it works:
295-
* XLogCtl->LogwrtResult is protected by info_lck
296-
* XLogCtl->Write.LogwrtResult is protected by WALWriteLock
297-
* XLogCtl->Insert.LogwrtResult is protected by WALInsertLock
298-
* One must hold the associated lock to read or write any of these, but
299-
* of course no lock is needed to read/write the unshared LogwrtResult.
300-
*
301-
* XLogCtl->LogwrtResult and XLogCtl->Write.LogwrtResult are both "always
302-
* right", since both are updated by a write or flush operation before
303-
* it releases WALWriteLock. The point of keeping XLogCtl->Write.LogwrtResult
304-
* is that it can be examined/modified by code that already holds WALWriteLock
305-
* without needing to grab info_lck as well.
306-
*
307-
* XLogCtl->Insert.LogwrtResult may lag behind the reality of the other two,
308-
* but is updated when convenient. Again, it exists for the convenience of
309-
* code that is already holding WALInsertLock but not the other locks.
310-
*
311-
* The unshared LogwrtResult may lag behind any or all of these, and again
312-
* is updated when convenient.
292+
* To read XLogCtl->LogwrtResult, you must hold either info_lck or
293+
* WALWriteLock. To update it, you need to hold both locks. The point of
294+
* this arrangement is that the value can be examined by code that already
295+
* holds WALWriteLock without needing to grab info_lck as well. In addition
296+
* to the shared variable, each backend has a private copy of LogwrtResult,
297+
* which is updated when convenient.
313298
*
314299
* The request bookkeeping is simpler: there is a shared XLogCtl->LogwrtRqst
315300
* (protected by info_lck), but we don't need to cache any copies of it.
316301
*
317-
* Note that this all works because the request and result positions can only
318-
* advance forward, never back up, and so we can easily determine which of two
319-
* values is "more up to date".
320-
*
321302
* info_lck is only held long enough to read/update the protected variables,
322303
* so it's a plain spinlock. The other locks are held longer (potentially
323304
* over I/O operations), so we use LWLocks for them. These locks are:
@@ -354,7 +335,6 @@ typedef struct XLogwrtResult
354335
*/
355336
typedef struct XLogCtlInsert
356337
{
357-
XLogwrtResult LogwrtResult; /* a recent value of LogwrtResult */
358338
XLogRecPtr PrevRecord; /* start of previously-inserted record */
359339
int curridx; /* current block index in cache */
360340
XLogPageHeader currpage; /* points to header of block in cache */
@@ -388,7 +368,6 @@ typedef struct XLogCtlInsert
388368
*/
389369
typedef struct XLogCtlWrite
390370
{
391-
XLogwrtResult LogwrtResult; /* current value of LogwrtResult */
392371
int curridx; /* cache index of next block to write */
393372
pg_time_t lastSegSwitchTime; /* time of last xlog segment switch */
394373
} XLogCtlWrite;
@@ -403,7 +382,6 @@ typedef struct XLogCtlData
403382

404383
/* Protected by info_lck: */
405384
XLogwrtRqst LogwrtRqst;
406-
XLogwrtResult LogwrtResult;
407385
uint32 ckptXidEpoch; /* nextXID & epoch of latest checkpoint */
408386
TransactionId ckptXid;
409387
XLogRecPtr asyncXactLSN; /* LSN of newest async commit/abort */
@@ -413,6 +391,12 @@ typedef struct XLogCtlData
413391
/* Protected by WALWriteLock: */
414392
XLogCtlWrite Write;
415393

394+
/*
395+
* Protected by info_lck and WALWriteLock (you must hold either lock to
396+
* read it, but both to update)
397+
*/
398+
XLogwrtResult LogwrtResult;
399+
416400
/*
417401
* These values do not change after startup, although the pointed-to pages
418402
* and xlblocks values certainly do. Permission to read/write the pages
@@ -1015,7 +999,7 @@ begin:;
1015999
}
10161000

10171001
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
1018-
LogwrtResult = XLogCtl->Write.LogwrtResult;
1002+
LogwrtResult = XLogCtl->LogwrtResult;
10191003
if (!XLByteLE(RecPtr, LogwrtResult.Flush))
10201004
{
10211005
XLogwrtRqst FlushRqst;
@@ -1188,8 +1172,6 @@ begin:;
11881172
SpinLockRelease(&xlogctl->info_lck);
11891173
}
11901174

1191-
Write->LogwrtResult = LogwrtResult;
1192-
11931175
LWLockRelease(WALWriteLock);
11941176

11951177
updrqst = false; /* done already */
@@ -1477,18 +1459,13 @@ static bool
14771459
AdvanceXLInsertBuffer(bool new_segment)
14781460
{
14791461
XLogCtlInsert *Insert = &XLogCtl->Insert;
1480-
XLogCtlWrite *Write = &XLogCtl->Write;
14811462
int nextidx = NextBufIdx(Insert->curridx);
14821463
bool update_needed = true;
14831464
XLogRecPtr OldPageRqstPtr;
14841465
XLogwrtRqst WriteRqst;
14851466
XLogRecPtr NewPageEndPtr;
14861467
XLogPageHeader NewPage;
14871468

1488-
/* Use Insert->LogwrtResult copy if it's more fresh */
1489-
if (XLByteLT(LogwrtResult.Write, Insert->LogwrtResult.Write))
1490-
LogwrtResult = Insert->LogwrtResult;
1491-
14921469
/*
14931470
* Get ending-offset of the buffer page we need to replace (this may be
14941471
* zero if the buffer hasn't been used yet). Fall through if it's already
@@ -1516,21 +1493,19 @@ AdvanceXLInsertBuffer(bool new_segment)
15161493

15171494
update_needed = false; /* Did the shared-request update */
15181495

1519-
if (XLByteLE(OldPageRqstPtr, LogwrtResult.Write))
1520-
{
1521-
/* OK, someone wrote it already */
1522-
Insert->LogwrtResult = LogwrtResult;
1523-
}
1524-
else
1496+
/*
1497+
* Now that we have an up-to-date LogwrtResult value, see if we still
1498+
* need to write it or if someone else already did.
1499+
*/
1500+
if (!XLByteLE(OldPageRqstPtr, LogwrtResult.Write))
15251501
{
15261502
/* Must acquire write lock */
15271503
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
1528-
LogwrtResult = Write->LogwrtResult;
1504+
LogwrtResult = XLogCtl->LogwrtResult;
15291505
if (XLByteLE(OldPageRqstPtr, LogwrtResult.Write))
15301506
{
15311507
/* OK, someone wrote it already */
15321508
LWLockRelease(WALWriteLock);
1533-
Insert->LogwrtResult = LogwrtResult;
15341509
}
15351510
else
15361511
{
@@ -1544,7 +1519,6 @@ AdvanceXLInsertBuffer(bool new_segment)
15441519
WriteRqst.Flush.xrecoff = 0;
15451520
XLogWrite(WriteRqst, false, false);
15461521
LWLockRelease(WALWriteLock);
1547-
Insert->LogwrtResult = LogwrtResult;
15481522
TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE();
15491523
}
15501524
}
@@ -1697,7 +1671,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
16971671
/*
16981672
* Update local LogwrtResult (caller probably did this already, but...)
16991673
*/
1700-
LogwrtResult = Write->LogwrtResult;
1674+
LogwrtResult = XLogCtl->LogwrtResult;
17011675

17021676
/*
17031677
* Since successive pages in the xlog cache are consecutively allocated,
@@ -1931,8 +1905,6 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
19311905
xlogctl->LogwrtRqst.Flush = LogwrtResult.Flush;
19321906
SpinLockRelease(&xlogctl->info_lck);
19331907
}
1934-
1935-
Write->LogwrtResult = LogwrtResult;
19361908
}
19371909

19381910
/*
@@ -2126,7 +2098,7 @@ XLogFlush(XLogRecPtr record)
21262098
continue;
21272099
}
21282100
/* Got the lock */
2129-
LogwrtResult = XLogCtl->Write.LogwrtResult;
2101+
LogwrtResult = XLogCtl->LogwrtResult;
21302102
if (!XLByteLE(record, LogwrtResult.Flush))
21312103
{
21322104
/* try to write/flush later additions to XLOG as well */
@@ -2268,7 +2240,7 @@ XLogBackgroundFlush(void)
22682240

22692241
/* now wait for the write lock */
22702242
LWLockAcquire(WALWriteLock, LW_EXCLUSIVE);
2271-
LogwrtResult = XLogCtl->Write.LogwrtResult;
2243+
LogwrtResult = XLogCtl->LogwrtResult;
22722244
if (!XLByteLE(WriteRqstPtr, LogwrtResult.Flush))
22732245
{
22742246
XLogwrtRqst WriteRqst;
@@ -6831,8 +6803,6 @@ StartupXLOG(void)
68316803

68326804
LogwrtResult.Write = LogwrtResult.Flush = EndOfLog;
68336805

6834-
XLogCtl->Write.LogwrtResult = LogwrtResult;
6835-
Insert->LogwrtResult = LogwrtResult;
68366806
XLogCtl->LogwrtResult = LogwrtResult;
68376807

68386808
XLogCtl->LogwrtRqst.Write = EndOfLog;

0 commit comments

Comments
 (0)