Re: AIO v2.5
Andres Freund <andres@anarazel.de>
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
aio: Fix assertion, clarify README
- 7b98c5536818 18.0 landed
- d3f97fd1dda3 19 (unreleased) landed
-
aio: Fix reference to outdated name
- f20a347e1a61 19 (unreleased) landed
- 95163cbe111c 18.0 landed
-
aio: Fix possible state confusions due to interrupt processing
- acad909321a4 18.0 landed
-
aio: Improve debug logging around waiting for IOs
- 039bfc457e43 18.0 landed
-
aio: Fix crash potential for pg_aios views due to late state update
- 0d9114b7040d 18.0 landed
-
Increase BAS_BULKREAD based on effective_io_concurrency
- 15f0cb26b530 18.0 landed
-
localbuf: Add Valgrind buffer access instrumentation
- 8ab4241b9f4f 18.0 landed
-
aio: Make AIO more compatible with valgrind
- 8e293e689bab 18.0 landed
-
aio: Avoid spurious coverity warning
- 57dec20fd469 18.0 landed
-
tests: Fix incompatibility of test_aio with *_FORCE_RELEASE
- a6285b150ad3 18.0 landed
-
tests: Cope with WARNINGs during failed CREATE DB on windows
- 43dca8a11624 18.0 landed
-
aio: Add errcontext for processing I/Os for another backend
- b3219c69fc1e 18.0 landed
-
aio: Add README.md explaining higher level design
- fdd146a8ef2b 18.0 landed
-
aio: Minor comment improvements
- e19dc74491e6 18.0 landed
-
aio: Add test_aio module
- 93bc3d75d8e1 18.0 landed
-
aio: Add pg_aios view
- 60f566b4f243 18.0 landed
-
docs: Add acronym and glossary entries for I/O and AIO
- 46250cdcb037 18.0 landed
-
Enable IO concurrency on all systems
- 2a5e709e721c 18.0 landed
-
read_stream: Introduce and use optional batchmode support
- ae3df4b34155 18.0 landed
-
docs: Reframe track_io_timing related docs as wait time
- b27f8637ea70 18.0 landed
-
bufmgr: Use AIO in StartReadBuffers()
- 12ce89fd0708 18.0 landed
-
bufmgr: Implement AIO read support
- 047cba7fa0f8 18.0 landed
-
aio: Add WARNING result status
- ef64fe26bad9 18.0 landed
-
Let caller of PageIsVerified() control ignore_checksum_failure
- d445990adc41 18.0 landed
-
pgstat: Allow checksum errors to be reported in critical sections
- b96d3c389755 18.0 landed
-
Add errhint_internal()
- 4244cf687697 18.0 landed
-
localbuf: Track pincount in BufferDesc as well
- d6d8054dc72d 18.0 landed
-
aio, bufmgr: Comment fixes/improvements
- 08ccd56ac765 18.0 landed
-
Fix mis-attribution of checksum failure stats to the wrong database
- dee80024688c 18.0 landed
-
aio: Implement support for reads in smgr/md/fd
- 50cb7505b301 18.0 landed
-
aio: Add io_method=io_uring
- c325a7633fcb 18.0 landed
-
aio: Add liburing dependency
- 8eadd5c73c44 18.0 landed
-
aio: Rename pgaio_io_prep_* to pgaio_io_start_*
- 9469d7fdd2bc 18.0 landed
-
aio: Pass result of local callbacks to ->report_return
- f321ec237a54 18.0 landed
-
aio: Be more paranoid about interrupts
- 96da9050a57a 18.0 landed
-
Redefine max_files_per_process to control additionally opened files
- adb5f85fa5a0 18.0 landed
-
aio: Change prefix of PgAioResultStatus values to PGAIO_RS_
- ca3067cc573d 18.0 landed
-
bufmgr: Improve stats when a buffer is read in concurrently
- 202b12774d09 18.0 landed
-
aio: Add io_method=worker
- 247ce06b883d 18.0 landed
-
aio: Infrastructure for io_method=worker
- 55b454d0e140 18.0 landed
-
aio: Add core asynchronous I/O infrastructure
- da7226993fd4 18.0 landed
-
aio: Basic subsystem initialization
- 02844012b304 18.0 landed
-
tests: Expand temp table tests to some pin related matters
- 1a22a8a0f131 18.0 landed
-
localbuf: Introduce FlushLocalBuffer()
- 4b4d33b9ea9f 18.0 landed
-
localbuf: Introduce TerminateLocalBufferIO()
- dd6f2618f681 18.0 landed
-
localbuf: Fix dangerous coding pattern in GetLocalVictimBuffer()
- fa6af9b25e4b 18.0 landed
-
localbuf: Introduce StartLocalBufferIO()
- 771ba90298e2 18.0 landed
-
localbuf: Introduce InvalidateLocalBuffer()
- 0762a151b0e0 18.0 landed
-
Allow lwlocks to be disowned
- f8d7f29b3e81 18.0 landed
-
Make jsonb casts to scalar types translate JSON null to SQL NULL.
- a5579a90af05 18.0 cited
-
bufmgr/smgr: Don't cross segment boundaries in StartReadBuffers()
- 755a4c10d19d 18.0 landed
-
Use aux process resource owner in walsender
- 57f370247127 18.0 landed
-
bufmgr: Return early in ScheduleBufferTagForWriteback() if fsync=off
- 488f826c729b 18.0 landed
Hi,
On 2025-03-25 17:19:15 -0700, Noah Misch wrote:
> On Mon, Mar 24, 2025 at 09:18:06PM -0400, Andres Freund wrote:
> > @@ -296,7 +299,9 @@ pgaio_io_call_complete_local(PgAioHandle *ioh)
> >
> > /*
> > * Note that we don't save the result in ioh->distilled_result, the local
> > - * callback's result should not ever matter to other waiters.
> > + * callback's result should not ever matter to other waiters. However, the
> > + * local backend does care, so we return the result as modified by local
> > + * callbacks, which then can be passed to ioh->report_return->result.
> > */
> > pgaio_debug_io(DEBUG3, ioh,
> > "after local completion: distilled result: (status %s, id %u, error_data %d, result %d), raw_result: %d",
>
> Should this debug message remove the word "distilled", since this commit
> solidifies distilled_result as referring to the complete_shared result?
Good point, updated.
> > Subject: [PATCH v2.12 01/28] aio: Be more paranoid about interrupts
> Ready for commit
> > Subject: [PATCH v2.12 02/28] aio: Pass result of local callbacks to
> > ->report_return
>
> Ready for commit w/ up to one cosmetic change:
>
And pushed. Together with the s/pgaio_io_prep_/s/pgaio_io_start_/ renaming
we've been discussing. Btw, I figured out the origin of that, I was just
mirroring the liburing API...
Thanks again for the reviews.
> > Subject: [PATCH v2.12 03/28] aio: Add liburing dependency
>
> Ready for commit
>
>
> > Subject: [PATCH v2.12 04/28] aio: Add io_method=io_uring
>
> Ready for commit w/ open_fd.fixup
Yay. Planning to push those soon.
> > Subject: [PATCH v2.12 05/28] aio: Implement support for reads in smgr/md/fd
>
> Ready for commit w/ up to two cosmetic changes:
Cool.
> > +/*
> > + * AIO error reporting callback for mdstartreadv().
> > + *
> > + * Errors are encoded as follows:
> > + * - PgAioResult.error_data != 0 encodes IO that failed with errno != 0
>
> I recommend replacing "errno != 0" with either "that errno" or "errno ==
> error_data".
Applied.
> Second, the aio_internal.h comment changes discussed in
> postgr.es/m/20250325155808.f7.nmisch@google.com and earlier.
Here's my current version of that:
* Note that the externally visible functions to start IO
* (e.g. FileStartReadV(), via pgaio_io_start_readv()) move an IO from
* PGAIO_HS_HANDED_OUT to at least PGAIO_HS_STAGED and at most
* PGAIO_HS_COMPLETED_LOCAL (at which point the handle will be reused).
Does that work?
I think I'll push that as part of the comment updates patch instead of
"Implement support for reads in smgr/md/fd", unless you see a reason to do so
differently. I'd have done it in the patch to s/prep/start/, but then it would
reference functions that don't exist yet...
> > Subject: [PATCH v2.12 06/28] aio: Add README.md explaining higher level design
>
> Ready for commit
Cool.
Comments in it reference PGAIO_HCB_SHARED_BUFFER_READV, so I'm inclined to
reorder it until after "bufmgr: Implement AIO read support".
There's also a small change in a new patch in the series (not yet sent), due
to the changes related to emitting WARNINGs about checksum failures to the
client connection. I think that part is fine, but...
> (This and the previous patch have three spots that would change with the
> s/prep/start/ renames. No opinion on whether to rename before or rename
> after.)
I thought it'd be better to do the renaming first.
> > Subject: [PATCH v2.12 07/28] localbuf: Track pincount in BufferDesc as well
>
> The plan here looks good:
> postgr.es/m/dbeeaize47y7esifdrinpa2l7cqqb67k72exvuf3appyxywjnc@7bt76mozhcy2
> > Subject: [PATCH v2.12 08/28] bufmgr: Implement AIO read support
>
> See review here and later discussion:
> postgr.es/m/20250325022037.91.nmisch@google.com
I'm working on a version with those addressed.
> > Subject: [PATCH v2.12 09/28] bufmgr: Use AIO in StartReadBuffers()
>
> Ready for commit after a batch of small things, all but one of which have no
> implications beyond code cosmetics.
Yay.
> I like the test coverage (by the end of the patch series).
I'm really shocked just how bad our test coverage for a lot of this is today
:(
> For anyone else following, I found "diff -w" helpful for the bufmgr.c
> changes. That's because a key part is former WaitReadBuffers() code moving
> up an indentation level to its home in new subroutine AsyncReadBuffers().
For reviewing changes that move stuff around a lot I find this rather helpful:
git diff --color-moved --color-moved-ws=ignore-space-change
That highlights removed code differently from moved code, and due to
ignore-space-change considers code that changed just due to space changes, to
be moved.
> > Assert(*nblocks == 1 || allow_forwarding);
> > Assert(*nblocks > 0);
> > Assert(*nblocks <= MAX_IO_COMBINE_LIMIT);
> > + Assert(*nblocks == 1 || allow_forwarding);
>
> Duplicates the assert three lines back.
Ah, it was moved into ce1a75c4fea, which I didn't notice while rebasing...
> > + nblocks = aio_ret->result.result;
> > +
> > + elog(DEBUG3, "partial read, will retry");
> > +
> > + }
> > + else if (aio_ret->result.status == PGAIO_RS_ERROR)
> > + {
> > + pgaio_result_report(aio_ret->result, &aio_ret->target_data, ERROR);
> > + nblocks = 0; /* silence compiler */
> > + }
> >
> > Assert(nblocks > 0);
> > Assert(nblocks <= MAX_IO_COMBINE_LIMIT);
> >
> > + operation->nblocks_done += nblocks;
>
> I struggled somewhat from the variety of "nblocks" variables: this local
> nblocks, operation->nblocks, actual_nblocks, and *nblocks in/out parameters of
> some functions. No one of them is clearly wrong to use the name, and some of
> these names are preexisting. That said, if you see opportunities to push in
> the direction of more-specific names, I'd welcome it.
>
> For example, this local variable could become add_to_nblocks_done instead.
I named it "newly_read_blocks", hope that works?
> > + AsyncReadBuffers(operation, &nblocks);
>
> I suggest renaming s/nblocks/ignored_nblocks_progress/ here.
Adopted.
Unfortunately I didn't see a good way to reduce the amount of the other
nblocks variables, as they are all, I think, preexisting.
> > + * If we need to wait for IO before we can get a handle, submit already
> > + * staged IO first, so that other backends don't need to wait. There
>
> s/already staged/already-staged/. Normally I'd skip this as nitpicking, but I
> misread this particular sentence twice, as "submit" being the subject that
> "staged" something. (It's still nitpicking, alas.)
Makes sense - it doesn't help that it was at a linebreak...
> > /*
> > * How many neighboring-on-disk blocks can we scatter-read into other
> > * buffers at the same time? In this case we don't wait if we see an
> > - * I/O already in progress. We already hold BM_IO_IN_PROGRESS for the
> > + * I/O already in progress. We already set BM_IO_IN_PROGRESS for the
> > * head block, so we should get on with that I/O as soon as possible.
> > - * We'll come back to this block again, above.
> > + *
> > + * We'll come back to this block in the next call to
> > + * StartReadBuffers() -> AsyncReadBuffers().
>
> Did this mean to say "WaitReadBuffers() -> AsyncReadBuffers()"? I'm guessing
> so, since WaitReadBuffers() is the one that loops. It might be referring to
> read_stream_start_pending_read()'s next StartReadBuffers(), though.
I was referring to the latter, as that is the more common case (it's pretty
easy to hit if you e.g. have multiple sequential scans on the same table
going).
> I think this could just delete the last sentence. The function header comment
> already mentions the possibility of reading a subset of the request. This
> spot doesn't need to detail how the higher layers come back to here.
Agreed.
> > + smgrstartreadv(ioh, operation->smgr, forknum,
> > + blocknum + nblocks_done,
> > + io_pages, io_buffers_len);
> > + pgstat_count_io_op_time(io_object, io_context, IOOP_READ,
> > + io_start, 1, *nblocks_progress * BLCKSZ);
>
> We don't assign *nblocks_progress until lower in the function, so I think
> "io_buffers_len" should replace "*nblocks_progress" here. (This is my only
> non-cosmetic comment on this patch.)
Good catch!
> > Subject: [PATCH v2.12 16/28] aio: Add test_aio module
>
> > +use List::Util qw(sample);
>
> sample() is new in 2020:
> https://metacpan.org/release/PEVANS/Scalar-List-Utils-1.68/source/Changes#L100
>
> Hence, I'd expect some buildfarm failures. I'd try to use shuffle(), then
> take the first N elements.
Hah. Bilal's patch was using shuffe(). I wanted to reduce the number of
iterations and first did as you suggest and then saw that there's a nicer
way...
Done that way again...
> > +++ b/src/test/modules/test_aio/test_aio.c
> > @@ -0,0 +1,712 @@
> > +/*-------------------------------------------------------------------------
> > + *
> > + * delay_execution.c
> > + * Test module to allow delay between parsing and execution of a query.
> > + *
> > + * The delay is implemented by taking and immediately releasing a specified
> > + * advisory lock. If another process has previously taken that lock, the
> > + * current process will be blocked until the lock is released; otherwise,
> > + * there's no effect. This allows an isolationtester script to reliably
> > + * test behaviors where some specified action happens in another backend
> > + * between parsing and execution of any desired query.
> > + *
> > + * Copyright (c) 2020-2025, PostgreSQL Global Development Group
> > + *
> > + * IDENTIFICATION
> > + * src/test/modules/test_aio/test_aio.c
>
> To elaborate on my last review, the entire header comment was a copy from
> delay_execution.c. v2.12 fixes the IDENTIFICATION, but the rest needs
> updates.
I was really too tired that day... Embarassing.
Greetings,
Andres Freund