From f7c6a46ea2d721e472237e00fd2404081a4ddc75 Mon Sep 17 00:00:00 2001 From: Claudio Freire Date: Fri, 2 Sep 2016 23:33:48 -0300 Subject: [PATCH 1/2] Vacuum: prefetch buffers on backward scan This patch speeds up truncation by prefetching buffers during the backward scan phase just prior to truncation. This optimization helps rotating media because disk rotation induces a buffer-to-buffer latency of roughly a whole rotation when reading backwards, such disks are usually optimized for forward scans. Prefetching buffers in larger chunks ameliorates the issue considerably and is otherwise harmless. The prefetch amount should also not be an issue on SSD, which won't benefit from the optimization, but won't be hurt either. --- src/backend/commands/vacuumlazy.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index b5fb325..854bce3 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -1825,7 +1825,7 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats) static BlockNumber count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats) { - BlockNumber blkno; + BlockNumber blkno, prefetchBlkno; instr_time starttime; /* Initialize the starttime if we check for conflicting lock requests */ @@ -1833,6 +1833,8 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats) /* Strange coding of loop control is needed because blkno is unsigned */ blkno = vacrelstats->rel_pages; + prefetchBlkno = blkno & ~0x1f; + prefetchBlkno = (prefetchBlkno > 32) ? prefetchBlkno - 32 : 0; while (blkno > vacrelstats->nonempty_pages) { Buffer buf; @@ -1882,6 +1884,23 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats) blkno--; + /* + * Speed up reads on rotating rust by prefetching a few blocks ahead. + * Backward scans on rotary disks are slow if done one buffer at a time + * because readahead won't kick in on most OSes, and each buffer will + * have to wait for the platter to do a full rotation. + * Should be harmless on SSD. + */ + if (blkno <= prefetchBlkno) { + BlockNumber pblkno; + if (prefetchBlkno >= 32) + prefetchBlkno -= 32; + else + prefetchBlkno = 0; + for (pblkno = prefetchBlkno; pblkno < blkno; pblkno++) + PrefetchBuffer(onerel, MAIN_FORKNUM, pblkno); + } + buf = ReadBufferExtended(onerel, MAIN_FORKNUM, blkno, RBM_NORMAL, vac_strategy); -- 1.8.4.5