v4-0004-Merge-partition-locks-array-with-buffer-locks-arr.patch
application/octet-stream
Filename: v4-0004-Merge-partition-locks-array-with-buffer-locks-arr.patch
Type: application/octet-stream
Part: 4
Patch
Format: format-patch
Series: patch v4-0004
Subject: Merge partition locks array with buffer locks array
| File | + | − |
|---|---|---|
| src/backend/access/transam/slru.c | 64 | 58 |
| src/include/access/slru.h | 5 | 5 |
From 30cc4cc9d7f2c65bfa072349ddd26aaa3b3ae0cd Mon Sep 17 00:00:00 2001
From: Dilip Kumar <dilip.kumar@enterprisedb.com>
Date: Thu, 2 Nov 2023 10:59:03 +0530
Subject: [PATCH v4 4/5] Merge partition locks array with buffer locks array
This will help us getting the part_cur_lru_count in same cacheline
which is frequently accessed in SlruRecentlyUsed.
---
src/backend/access/transam/slru.c | 122 ++++++++++++++++--------------
src/include/access/slru.h | 10 +--
2 files changed, 69 insertions(+), 63 deletions(-)
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index ab7cd276ce..8b89a86a10 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -152,8 +152,7 @@ SimpleLruStructSize(int nslots, int nlsns)
sz += MAXALIGN(nslots * sizeof(bool)); /* page_dirty[] */
sz += MAXALIGN(nslots * sizeof(int)); /* page_number[] */
sz += MAXALIGN(nslots * sizeof(int)); /* page_lru_count[] */
- sz += MAXALIGN(nslots * sizeof(LWLockPadded)); /* buffer_locks[] */
- sz += MAXALIGN(SLRU_NUM_PARTITIONS * sizeof(LWLockPadded)); /* part_locks[] */
+ sz += MAXALIGN((nslots + SLRU_NUM_PARTITIONS) * sizeof(LWLockPadded)); /* locks[] */
sz += MAXALIGN(SLRU_NUM_PARTITIONS * sizeof(int)); /* part_cur_lru_count[] */
if (nlsns > 0)
@@ -231,10 +230,8 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
offset += MAXALIGN(nslots * sizeof(int));
/* Initialize LWLocks */
- shared->buffer_locks = (LWLockPadded *) (ptr + offset);
- offset += MAXALIGN(nslots * sizeof(LWLockPadded));
- shared->part_locks = (LWLockPadded *) (ptr + offset);
- offset += MAXALIGN(SLRU_NUM_PARTITIONS * sizeof(LWLockPadded));
+ shared->locks = (LWLockPadded *) (ptr + offset);
+ offset += MAXALIGN((nslots + SLRU_NUM_PARTITIONS) * sizeof(LWLockPadded));
shared->part_cur_lru_count = (int *) (ptr + offset);
offset += MAXALIGN(SLRU_NUM_PARTITIONS * sizeof(int));
@@ -247,8 +244,7 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
ptr += BUFFERALIGN(offset);
for (slotno = 0; slotno < nslots; slotno++)
{
- LWLockInitialize(&shared->buffer_locks[slotno].lock,
- buffer_tranche_id);
+ LWLockInitialize(&shared->locks[slotno].lock, buffer_tranche_id);
shared->page_buffer[slotno] = ptr;
shared->page_status[slotno] = SLRU_PAGE_EMPTY;
@@ -259,7 +255,7 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
/* Initialize partition locks for each buffer partition. */
for (partno = 0; partno < SLRU_NUM_PARTITIONS; partno++)
{
- LWLockInitialize(&shared->part_locks[partno].lock,
+ LWLockInitialize(&shared->locks[nslots + partno].lock,
part_tranche_id);
shared->part_cur_lru_count[partno] = 0;
}
@@ -369,12 +365,13 @@ SimpleLruWaitIO(SlruCtl ctl, int slotno)
{
SlruShared shared = ctl->shared;
int partno = slotno / ctl->part_size;
+ int partlockoffset = shared->num_slots + partno;
/* See notes at top of file */
- LWLockRelease(&shared->part_locks[partno].lock);
- LWLockAcquire(&shared->buffer_locks[slotno].lock, LW_SHARED);
- LWLockRelease(&shared->buffer_locks[slotno].lock);
- LWLockAcquire(&shared->part_locks[partno].lock, LW_EXCLUSIVE);
+ LWLockRelease(&shared->locks[partlockoffset].lock);
+ LWLockAcquire(&shared->locks[slotno].lock, LW_SHARED);
+ LWLockRelease(&shared->locks[slotno].lock);
+ LWLockAcquire(&shared->locks[partlockoffset].lock, LW_EXCLUSIVE);
/*
* If the slot is still in an io-in-progress state, then either someone
@@ -387,7 +384,7 @@ SimpleLruWaitIO(SlruCtl ctl, int slotno)
if (shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS ||
shared->page_status[slotno] == SLRU_PAGE_WRITE_IN_PROGRESS)
{
- if (LWLockConditionalAcquire(&shared->buffer_locks[slotno].lock, LW_SHARED))
+ if (LWLockConditionalAcquire(&shared->locks[slotno].lock, LW_SHARED))
{
/* indeed, the I/O must have failed */
if (shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS)
@@ -400,7 +397,7 @@ SimpleLruWaitIO(SlruCtl ctl, int slotno)
shared->page_status[slotno] = SLRU_PAGE_VALID;
shared->page_dirty[slotno] = true;
}
- LWLockRelease(&shared->buffer_locks[slotno].lock);
+ LWLockRelease(&shared->locks[slotno].lock);
}
}
}
@@ -433,6 +430,7 @@ SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
{
int slotno;
int partno;
+ int banklockoffset;
bool ok;
/* See if page already is in memory; if not, pick victim slot */
@@ -477,11 +475,12 @@ SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
shared->page_dirty[slotno] = false;
/* Acquire per-buffer lock (cannot deadlock, see notes at top) */
- LWLockAcquire(&shared->buffer_locks[slotno].lock, LW_EXCLUSIVE);
+ LWLockAcquire(&shared->locks[slotno].lock, LW_EXCLUSIVE);
partno = slotno / ctl->part_size;
+ banklockoffset = shared->num_slots + partno;
/* Release control lock while doing I/O */
- LWLockRelease(&shared->part_locks[partno].lock);
+ LWLockRelease(&shared->locks[banklockoffset].lock);
/* Do the read */
ok = SlruPhysicalReadPage(ctl, pageno, slotno);
@@ -490,7 +489,7 @@ SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
SimpleLruZeroLSNs(ctl, slotno);
/* Re-acquire control lock and update page state */
- LWLockAcquire(&shared->part_locks[partno].lock, LW_EXCLUSIVE);
+ LWLockAcquire(&shared->locks[banklockoffset].lock, LW_EXCLUSIVE);
Assert(shared->page_number[slotno] == pageno &&
shared->page_status[slotno] == SLRU_PAGE_READ_IN_PROGRESS &&
@@ -504,7 +503,7 @@ SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
shared->page_status[slotno] = SLRU_PAGE_EMPTY;
}
- LWLockRelease(&shared->buffer_locks[slotno].lock);
+ LWLockRelease(&shared->locks[slotno].lock);
/* Now it's okay to ereport if we failed */
if (!ok)
@@ -539,12 +538,14 @@ SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
SlruShared shared = ctl->shared;
int slotno;
int partno;
+ int partlockoffset;
/* Determine partition number for the page. */
partno = SlruMappingPartNo(ctl, pageno);
+ partlockoffset = shared->num_slots + partno;
/* Try to find the page while holding only shared partition lock */
- LWLockAcquire(&shared->part_locks[partno].lock, LW_SHARED);
+ LWLockAcquire(&shared->locks[partlockoffset].lock, LW_SHARED);
/* See if page is already in a buffer */
slotno = SlruMappingFind(ctl, pageno);
@@ -564,8 +565,8 @@ SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
}
/* No luck, so switch to normal exclusive lock and do regular read */
- LWLockRelease(&shared->part_locks[partno].lock);
- LWLockAcquire(&shared->part_locks[partno].lock, LW_EXCLUSIVE);
+ LWLockRelease(&shared->locks[partlockoffset].lock);
+ LWLockAcquire(&shared->locks[partlockoffset].lock, LW_EXCLUSIVE);
return SimpleLruReadPage(ctl, pageno, true, xid);
}
@@ -588,6 +589,7 @@ SlruInternalWritePage(SlruCtl ctl, int slotno, SlruWriteAll fdata)
int pageno = shared->page_number[slotno];
bool ok;
int partno = slotno / ctl->part_size;
+ int partlockoffset = shared->num_slots + partno;
/* If a write is in progress, wait for it to finish */
while (shared->page_status[slotno] == SLRU_PAGE_WRITE_IN_PROGRESS &&
@@ -613,10 +615,10 @@ SlruInternalWritePage(SlruCtl ctl, int slotno, SlruWriteAll fdata)
shared->page_dirty[slotno] = false;
/* Acquire per-buffer lock (cannot deadlock, see notes at top) */
- LWLockAcquire(&shared->buffer_locks[slotno].lock, LW_EXCLUSIVE);
+ LWLockAcquire(&shared->locks[slotno].lock, LW_EXCLUSIVE);
/* Release control lock while doing I/O */
- LWLockRelease(&shared->part_locks[partno].lock);
+ LWLockRelease(&shared->locks[partlockoffset].lock);
/* Do the write */
ok = SlruPhysicalWritePage(ctl, pageno, slotno, fdata);
@@ -631,7 +633,7 @@ SlruInternalWritePage(SlruCtl ctl, int slotno, SlruWriteAll fdata)
}
/* Re-acquire control lock and update page state */
- LWLockAcquire(&shared->part_locks[partno].lock, LW_EXCLUSIVE);
+ LWLockAcquire(&shared->locks[partlockoffset].lock, LW_EXCLUSIVE);
Assert(shared->page_number[slotno] == pageno &&
shared->page_status[slotno] == SLRU_PAGE_WRITE_IN_PROGRESS);
@@ -642,7 +644,7 @@ SlruInternalWritePage(SlruCtl ctl, int slotno, SlruWriteAll fdata)
shared->page_status[slotno] = SLRU_PAGE_VALID;
- LWLockRelease(&shared->buffer_locks[slotno].lock);
+ LWLockRelease(&shared->locks[slotno].lock);
/* Now it's okay to ereport if we failed */
if (!ok)
@@ -1219,7 +1221,7 @@ SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
int slotno;
int pageno = 0;
int i;
- int lastpartno = 0;
+ int prevlockoffset = shared->num_slots;
bool ok;
/* update the stats counter of flushes */
@@ -1230,17 +1232,17 @@ SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
*/
fdata.num_files = 0;
- LWLockAcquire(&shared->part_locks[0].lock, LW_EXCLUSIVE);
+ LWLockAcquire(&shared->locks[prevlockoffset].lock, LW_EXCLUSIVE);
for (slotno = 0; slotno < shared->num_slots; slotno++)
{
- int curpartno = slotno / ctl->part_size;
+ int curlockoffset = shared->num_slots + slotno / ctl->part_size;
- if (curpartno != lastpartno)
+ if (curlockoffset != prevlockoffset)
{
- LWLockRelease(&shared->part_locks[lastpartno].lock);
- LWLockAcquire(&shared->part_locks[curpartno].lock, LW_EXCLUSIVE);
- lastpartno = curpartno;
+ LWLockRelease(&shared->locks[prevlockoffset].lock);
+ LWLockAcquire(&shared->locks[curlockoffset].lock, LW_EXCLUSIVE);
+ prevlockoffset = curlockoffset;
}
SlruInternalWritePage(ctl, slotno, &fdata);
@@ -1256,7 +1258,7 @@ SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
!shared->page_dirty[slotno]));
}
- LWLockRelease(&shared->part_locks[lastpartno].lock);
+ LWLockRelease(&shared->locks[prevlockoffset].lock);
/*
* Now close any files that were open
@@ -1296,7 +1298,8 @@ SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
{
SlruShared shared = ctl->shared;
int slotno;
- int prevpartno;
+ int nslots = shared->num_slots;
+ int prevlockoffset;
/* update the stats counter of truncates */
pgstat_count_slru_truncate(shared->slru_stats_idx);
@@ -1322,21 +1325,21 @@ restart:
return;
}
- prevpartno = 0;
- LWLockAcquire(&shared->part_locks[prevpartno].lock, LW_EXCLUSIVE);
- for (slotno = 0; slotno < shared->num_slots; slotno++)
+ prevlockoffset = nslots;
+ LWLockAcquire(&shared->locks[prevlockoffset].lock, LW_EXCLUSIVE);
+ for (slotno = 0; slotno < nslots; slotno++)
{
- int curpartno = slotno / ctl->part_size;
+ int curlockoffset = nslots + (slotno / ctl->part_size);
/*
* If the curpartno is not same as prevpartno then release the lock on
* the prevpartno and acquire the lock on the curpartno.
*/
- if (curpartno != prevpartno)
+ if (curlockoffset != prevlockoffset)
{
- LWLockRelease(&shared->part_locks[prevpartno].lock);
- LWLockAcquire(&shared->part_locks[curpartno].lock, LW_EXCLUSIVE);
- prevpartno = curpartno;
+ LWLockRelease(&shared->locks[prevlockoffset].lock);
+ LWLockAcquire(&shared->locks[curlockoffset].lock, LW_EXCLUSIVE);
+ prevlockoffset = curlockoffset;
}
if (shared->page_status[slotno] == SLRU_PAGE_EMPTY)
@@ -1370,11 +1373,11 @@ restart:
else
SimpleLruWaitIO(ctl, slotno);
- LWLockRelease(&shared->part_locks[prevpartno].lock);
+ LWLockRelease(&shared->locks[prevlockoffset].lock);
goto restart;
}
- LWLockRelease(&shared->part_locks[prevpartno].lock);
+ LWLockRelease(&shared->locks[prevlockoffset].lock);
/* Now we can remove the old segment(s) */
(void) SlruScanDirectory(ctl, SlruScanDirCbDeleteCutoff, &cutoffPage);
@@ -1415,28 +1418,29 @@ SlruDeleteSegment(SlruCtl ctl, int segno)
SlruShared shared = ctl->shared;
int slotno;
bool did_write;
- int prevpartno = 0;
+ int nslots = shared->num_slots;
+ int prevlockoffset = nslots;
/* Clean out any possibly existing references to the segment. */
- LWLockAcquire(&shared->part_locks[prevpartno].lock, LW_EXCLUSIVE);
+ LWLockAcquire(&shared->locks[prevlockoffset].lock, LW_EXCLUSIVE);
restart:
did_write = false;
- for (slotno = 0; slotno < shared->num_slots; slotno++)
+ for (slotno = 0; slotno < nslots; slotno++)
{
int pagesegno;
- int curpartno;
+ int curlockoffset;
- curpartno = slotno / ctl->part_size;
+ curlockoffset = nslots + (slotno / ctl->part_size);
/*
* If the curpartno is not same as prevpartno then release the lock on
* the prevpartno and acquire the lock on the curpartno.
*/
- if (curpartno != prevpartno)
+ if (curlockoffset != prevlockoffset)
{
- LWLockRelease(&shared->part_locks[prevpartno].lock);
- LWLockAcquire(&shared->part_locks[curpartno].lock, LW_EXCLUSIVE);
- prevpartno = curpartno;
+ LWLockRelease(&shared->locks[prevlockoffset].lock);
+ LWLockAcquire(&shared->locks[curlockoffset].lock, LW_EXCLUSIVE);
+ prevlockoffset = curlockoffset;
}
pagesegno = shared->page_number[slotno] / SLRU_PAGES_PER_SEGMENT;
@@ -1474,7 +1478,7 @@ restart:
SlruInternalDeleteSegment(ctl, segno);
- LWLockRelease(&shared->part_locks[prevpartno].lock);
+ LWLockRelease(&shared->locks[prevlockoffset].lock);
}
/*
@@ -1816,7 +1820,7 @@ SimpleLruGetPartitionLock(SlruCtl ctl, int pageno)
{
int partno = SlruMappingPartNo(ctl, pageno);
- return &(ctl->shared->part_locks[partno].lock);
+ return &(ctl->shared->locks[ctl->shared->num_slots + partno].lock);
}
/*
@@ -1827,9 +1831,10 @@ SimpleLruLockAllPartitions(SlruCtl ctl, LWLockMode mode)
{
SlruShared shared = ctl->shared;
int partno;
+ int nslots = shared->num_slots;
for (partno = 0; partno < SLRU_NUM_PARTITIONS; partno++)
- LWLockAcquire(&shared->part_locks[partno].lock, mode);
+ LWLockAcquire(&shared->locks[nslots + partno].lock, mode);
}
/*
@@ -1840,7 +1845,8 @@ SimpleLruUnLockAllPartitions(SlruCtl ctl)
{
SlruShared shared = ctl->shared;
int partno;
+ int nslots = shared->num_slots;
for (partno = 0; partno < SLRU_NUM_PARTITIONS; partno++)
- LWLockRelease(&shared->part_locks[partno].lock);
+ LWLockRelease(&shared->locks[nslots + partno].lock);
}
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index e6c54d5519..ac1227f29f 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -70,14 +70,14 @@ typedef struct SlruSharedData
bool *page_dirty;
int *page_number;
int *page_lru_count;
- LWLockPadded *buffer_locks;
/*
- * Locks to protect the in memory buffer slot access in per SLRU bank. The
- * buffer_locks protects the I/O on each buffer slots whereas this lock
- * protect the in memory operation on the buffer within one SLRU bank.
+ * This contains nslots numbers of buffers locks and nparts numbers of
+ * part locks. The buffer locks protects the I/O on each buffer slots
+ * whereas the part lock protect the in memory operation on the buffer
+ * within one SLRU part.
*/
- LWLockPadded *part_locks;
+ LWLockPadded *locks;
/*----------
* Instead of global counter we maintain a partition-wise lru counter
--
2.39.2 (Apple Git-143)