Re: aio: Async fsyncs for crash recovery and checkpointer - Mailing list pgsql-hackers

From Nazir Bilal Yavuz
Subject Re: aio: Async fsyncs for crash recovery and checkpointer
Date
Msg-id CAN55FZ2WnU9pMtjKP-=V+41gzPABuY6hXB_xO3CnOuMvhTVJvg@mail.gmail.com
Whole thread
Responses Re: aio: Async fsyncs for crash recovery and checkpointer
List pgsql-hackers
Hi,

Thank you for looking into this!

On Thu, 3 Sept 2026 at 16:15, Yuhang Qiu <iamqyh@gmail.com> wrote:
>
> The overall direction looks good to me. A few points:
>
> > This patch implements async fsyncs for crash recovery and checkpoints by
> > using the AIO system.
>
> For crash recovery, Linux already has `recovery_init_sync_method=syncfs` as an
> alternative to per-file fsyncs. I think it would be useful to include that in
> the `SyncDataDirectory()` benchmark.

Good point. I tested recovery_init_sync_method=syncfs and it seems it
is better than or on par with fsync and AIO. Here are two different
benchmark results:

io_method  | recovery_init_sync_method |         startup (ms) |         speedup
-----------+---------------------------+----------------------+----------------
sync       | fsync                     |                609.4 |           1.00x
worker     | fsync                     |                610.8 |           1.00x
io_uring   | fsync                     |                308.6 |           1.97x
sync       | syncfs                    |                210.7 |           2.89x

io_method  | recovery_init_sync_method |         startup (ms) |         speedup
-----------+---------------------------+----------------------+----------------
sync       | fsync                     |                609.2 |           1.00x
worker     | fsync                     |                610.0 |           1.00x
io_uring   | fsync                     |                211.0 |           2.89x
sync       | syncfs                    |                209.0 |           2.91x


> > I will change the reopen interface so that ordinary failures return
> > `-errno`.
>
> Agreed. I think all AIO target reopen callbacks should follow this convention.
> Relation fsyncs can hit the same problem through `smgr_aio_reopen()`, not only
> SLRUs.

I played with that a bit but there were some problems; it was more
complicated than I thought. If we want to return -errno, we lose quite
a bit of error information because we don't reach the actual error
message. We short-circuit these error messages to return -errno and
continue without terminating the worker process.

For now, ordinary reopen failures for both relation and SLRU fsyncs
return -errno. This allows the checkpointer to apply its cancellation,
retry, and error-handling policy without terminating the I/O worker.
Read and write IO reopening retains its existing error handling. I
will continue working to improve this.


> > It uses both io_max_concurrency and the file descriptor budget to determine
> > max number of available in-flight fsync I/Os.
>
> I wonder whether submitting a batch of concurrent fsyncs could cause an I/O
> storm and hurt foreground I/O latency.

I think this is a valid concern. With io_method=worker, fsyncs also
share the worker pool with reads so that could cause a performance
problems. However, I think increasing the number of worker processes
should solve this problem.


> The `max_safe_fds / 6` cap protects the `AllocateDesc` budget used by
> `OpenTransientFile()`, while relation fsyncs use VFDs. Should the descriptor
> cap apply only to handlers that use `OpenTransientFile()`?

Done. Relation fsync requests now use io_max_concurrency as their
limit. For handlers that hold transient descriptors in the
issuingprocess, the limit is also capped at max_safe_fds / 6.


Here are some additional updates compared to v1:

- 0001 enables fsync on tests so CI will run tests with fsync enabled.

- 0002 clears SMGR caches for the worker processes. These caches are
created on the smgr_reopen path and not get destroyed later so these
remain for the lifetime of worker processes. Patch clears the SMGR
cache after a checkpoint and when the worker is not busy. I created
another thread for this [1].

- 0005 for reopen error changes.

- 0008 is for doc changes.

I am still working on the tests; no tests are included yet.


[1] https://postgr.es/m/CAN55FZ2BesKUnajdgpw1fPSe3S6_CHOugryaUEtD7vdP%3DdRKEQ%40mail.gmail.com

--
Regards,
Nazir Bilal Yavuz
Microsoft

Attachment

pgsql-hackers by date:

Previous
From: Amit Kapila
Date:
Subject: Re: Distinguish publication exclusions in object addresses
Next
From: Rafia Sabih
Date:
Subject: Re: Warn when creating or enabling a subscription with max_logical_replication_workers = 0