Re: Skip prefetch for block references that follow a FPW or WILL_INIT of the same block

From: Tomas Vondra <tomas(at)vondra(dot)me>
To: Jeremy Schneider <schneider(at)ardentperf(dot)com>, shihao zhong <zhong950419(at)gmail(dot)com>
Cc: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, SATYANARAYANA NARLAPURAM <satyanarlapuram(at)gmail(dot)com>, Ashutosh Sharma <ashu(dot)coek88(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Thomas Munro <thomas(dot)munro(at)gmail(dot)com>, Lakshmi N <lakshmin(dot)jhs(at)gmail(dot)com>
Subject: Re: Skip prefetch for block references that follow a FPW or WILL_INIT of the same block
Date: 2026-10-27 14:26:23
Message-ID: 7d439ce2-c024-4162-a609-8b49ff2a01b9@vondra.me
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 10/27/26 06:58, Jeremy Schneider wrote:
>
>
> On Mon, Oct 26, 2026 at 8:52 PM shihao zhong <zhong950419(at)gmail(dot)com
> <mailto:zhong950419(at)gmail(dot)com>> wrote:
>
> I did not find a 16x amplification diagram in your github link.
> Maybe I am missing
> something?
>
>
> The IOPS amplification was very clear from looking at the charts showing
> Azure IOPS for the primary on the replica. But you're right that the
> github link did not show the math. The 16x comes from the primary doing
> 128k reads for seqscan and vacuum (whether due to io_uring or os
> readahead) while the replica does 8k reads (i'm fairly confident linux
> wont do readahead).  But when I visually look at the charts, it actually
> seems a bit higher than 16x - the replica was pegged at 500 IOPS for
> over 30 minutes.  I'm doing a bit more testing now to see if I can
> illustrate this more clearly.
>

I believe you're right posix_fadvise(WILLNEED) effectively disables
kernel readhead - which is unfortunate, of course. I haven't looked at
the kernel code recently, but an easy way to verify that is with a
simple C program that issues fadvise + read on a file.

I'm attaching an example I just mashed together (ugly, likely dangerous)
that gets a preallocated file, and issues sequential fadvise+read calls
on it, in chunks of 16 x 8K blocks. Something like

--
gcc -o fadvise-readahead fadvise-readahead.c

dd if=/dev/random bs=1M of=test.file count=8192 status=progress

sync
echo 3 > /proc/sys/vm/drop_caches

./fadvise-readahead /mnt/data/test.file
--

With the fadvise calls in place, iostat -x -k says something like

Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz
nvme5n1 56423.00 451384.00 0.00 0.00 0.42 8.00

while with the fadvise calls commented out, it says

Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz
nvme5n1 14142.00 1808736.00 0.00 0.00 0.21 127.90

So the average request size goes from 8K to 128K, which is exactly what
readahead does. But only without the fadvise stuff.

This only matters if there actually is sequential pattern. I assumed
it'd not make a significant difference without the IOPS limit, due to
readahead built into the SSDs, but it seems I was wrong (per the iostat
output above). On a random access it's a clear win, ofc.

I don't have a great solution to this. We'd need to do I/O combining,
similarly to what happens on the primary. I'm not sure if it's feasible,
or if it'd be better to rework the prefetcher to use read_stream (which
has all of this built in).

Sure, disabling prefetching is an option. But I'd point out the
prefetching was conveived as a solution to issues with ever-growing
replication lag. So it's a trade off.

regards

--
Tomas Vondra

Attachment Content-Type Size
fadvise-readahead.c text/x-csrc 1.4 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Jakub Wartak 2026-10-27 14:27:56 Re: pg_*_advice: tsv load failure, etc.
Previous Message shihao zhong 2026-10-27 14:24:05 Re: Skip prefetch for block references that follow a FPW or WILL_INIT of the same block