Skip to content

Commit

Permalink
Optimize prefetch patterns in both heap seqscan and vacuum scans.
Browse files Browse the repository at this point in the history
Previously, we called PrefetchBuffer [NBlkScanned * seqscan_prefetch_buffers]
times in each of those situations, but now only NBlkScanned.

In addition, the prefetch mechanism for the vacuum scans is now based on
blocks instead of tuples - improving the efficiency.
  • Loading branch information
MMeent committed Oct 24, 2022
1 parent b1c21a4 commit 0a675c1
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 21 deletions.
25 changes: 19 additions & 6 deletions src/backend/access/heap/heapam.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,19 +400,32 @@ heapgetpage(TableScanDesc sscan, BlockNumber page)
CHECK_FOR_INTERRUPTS();

/* Prefetch next block */
if (enable_seqscan_prefetch)
if (enable_seqscan_prefetch && seqscan_prefetch_buffers > 0)
{
int prefetch_limit = seqscan_prefetch_buffers;
uint32 prefetch_limit = seqscan_prefetch_buffers;
BlockNumber prefetch_start = page;
ParallelBlockTableScanWorker pbscanwork = scan->rs_parallelworkerdata;

if (pbscanwork != NULL && pbscanwork->phsw_chunk_remaining < prefetch_limit)
prefetch_limit = pbscanwork->phsw_chunk_remaining;
if (page + prefetch_limit >= scan->rs_nblocks)
prefetch_limit = scan->rs_nblocks - page - 1;

/*
* If we've started prefetching buffers, we don't have to prefetch
* all pages in page..page + n, but only page + n; saving N-1 prefetch
* calls.
*/
if (scan->rs_startblock != page)
{
prefetch_start = (page + prefetch_limit - 1) % scan->rs_nblocks;
prefetch_limit = 1;
}
else
prefetch_start = page;

RelationOpenSmgr(scan->rs_base.rs_rd);
smgr_reset_prefetch(scan->rs_base.rs_rd->rd_smgr);
for (int i = 1; i <= prefetch_limit; i++)
PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM, page+i);
PrefetchBuffer(scan->rs_base.rs_rd, MAIN_FORKNUM,
(prefetch_start+i) % scan->rs_nblocks);
}

/* read page using selected strategy */
Expand Down
56 changes: 41 additions & 15 deletions src/backend/access/heap/vacuumlazy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1218,14 +1218,6 @@ lazy_scan_heap(LVRelState *vacrel, VacuumParams *params, bool aggressive)
*/
visibilitymap_pin(vacrel->rel, blkno, &vmbuffer);

if (enable_seqscan_prefetch)
{
int prefetch_limit = Min(nblocks - blkno - 1, seqscan_prefetch_buffers);
RelationOpenSmgr(vacrel->rel);
smgr_reset_prefetch(vacrel->rel->rd_smgr);
for (int i = 1; i <= prefetch_limit; i++)
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, blkno+i);
}
buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno,
RBM_NORMAL, vacrel->bstrategy);

Expand Down Expand Up @@ -2323,7 +2315,8 @@ lazy_vacuum_all_indexes(LVRelState *vacrel)
static void
lazy_vacuum_heap_rel(LVRelState *vacrel)
{
int tupindex;
int tupindex,
ptupindex;
BlockNumber vacuumed_pages;
PGRUsage ru0;
Buffer vmbuffer = InvalidBuffer;
Expand All @@ -2346,6 +2339,7 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
vacuumed_pages = 0;

tupindex = 0;
ptupindex = 0;
while (tupindex < vacrel->dead_tuples->num_tuples)
{
BlockNumber tblk;
Expand All @@ -2356,14 +2350,46 @@ lazy_vacuum_heap_rel(LVRelState *vacrel)
vacuum_delay_point();

tblk = ItemPointerGetBlockNumber(&vacrel->dead_tuples->itemptrs[tupindex]);
if (enable_seqscan_prefetch)

if (enable_seqscan_prefetch && seqscan_prefetch_buffers > 0)
{
int prefetch_limit = Min(vacrel->dead_tuples->num_tuples - tupindex - 1, seqscan_prefetch_buffers);
RelationOpenSmgr(vacrel->rel);
smgr_reset_prefetch(vacrel->rel->rd_smgr);
for (int i = 1; i <= prefetch_limit; i++)
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, ItemPointerGetBlockNumber(&vacrel->dead_tuples->itemptrs[tupindex + i]));
/*
* If we're just starting out, prefetch N consecutive blocks.
* If not, only the next 1 block
*/
if (tupindex == 0)
{
int prefetch_limit = Min(vacrel->dead_tuples->num_tuples - tupindex - 1,
Min(vacrel->rel_pages,
seqscan_prefetch_buffers));
BlockNumber prev_prefetch = 0;

RelationOpenSmgr(vacrel->rel);

while (++ptupindex < vacrel->dead_tuples->num_tuples &&
prefetch_limit > 0)
{
ItemPointer ptr = &vacrel->dead_tuples->itemptrs[ptupindex];
if (ItemPointerGetBlockNumber(ptr) != prev_prefetch)
{
prev_prefetch = ItemPointerGetBlockNumber(ptr);
prefetch_limit -= 1;
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, prev_prefetch);
}
}
}
else
{
BlockNumber toPrefetch = ItemPointerGetBlockNumber(&vacrel->dead_tuples->itemptrs[ptupindex]);
while (ptupindex < vacrel->dead_tuples->num_tuples)
{
if (toPrefetch != ItemPointerGetBlockNumber(&vacrel->dead_tuples->itemptrs[ptupindex]))
break;
}
PrefetchBuffer(vacrel->rel, MAIN_FORKNUM, toPrefetch);
}
}

vacrel->blkno = tblk;
buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, tblk, RBM_NORMAL,
vacrel->bstrategy);
Expand Down

0 comments on commit 0a675c1

Please sign in to comment.