Re: Checkpointer write combining

From: Andrey Borodin <x4mmm(at)yandex-team(dot)ru>
To: Melanie Plageman <melanieplageman(at)gmail(dot)com>
Cc: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>, Nazir Bilal Yavuz <byavuz81(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Andres Freund <andres(at)anarazel(dot)de>, tristan(dot)yim(at)gmail(dot)com
Subject: Re: Checkpointer write combining
Date: 2026-09-14 18:29:36
Message-ID: 201425E8-D617-4971-BE7E-E94DDAF8356F@yandex-team.ru
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I continued reviewing v16, focusing on checkpointer and bgwriter.

In 0004:

> + CheckpointWriteDelay(flags, (double) num_processed / num_to_scan,
> + processed);

This is now called once per batch instead of once per processed buffer,
but each call can still sleep for at most 100 ms. This can make smaller
spread checkpoints finish much earlier.

On Linux, with shared_buffers = 128MB, fsync = off,
checkpoint_timeout = 30s and checkpoint_completion_target = 0.9,
I updated a 20000-row table after a fast checkpoint, then issued
CHECKPOINT (MODE spread). Each run wrote 1146 buffers:

pg_stat_io.writes write phase
master 1146 26.869s
v16, io_combine_limit=8kB 1146 26.166s
v16, default 128kB limit 75 7.121s
v16, per-buffer delay calls 75 26.259s

For the last row I restored per-buffer delay calls after releasing the
batch's locks. Could we preserve that pacing when combining writes?

In 0006:

> + for (; num_to_scan > 0; num_to_scan--, next_to_clean++)
> ...
> + if (++num_written >= bgwriter_lru_maxpages)
> {
> + PendingBgWriterStats.maxwritten_clean++;
> + break;
> }

Reaching the limit skips the for-loop update. The last buffer is
counted as reusable but omitted from scan progress. The saved position
still points to it. Advancing and wrapping the scan position after
selecting the buffer, before processing it, should avoid this.
The issue survives in BgwriterWriteBuffers() later in the series.

In 0018:

> + GatherContiguousDirtyBuffers(bufHdr, IOCONTEXT_NORMAL, &batch);
> + WriteBuffers(&batch);
> + CompleteWriteBuffers(&batch, wb_context);
> + num_written += batch.n;
>
> + if (num_written >= lru_maxpages)

The combined write can already exceed bgwriter_lru_maxpages by the time
we check it. Calling run_bgwriter_cleaner(1) in the existing test
writes all six contiguous buffers. Could GatherContiguousDirtyBuffers()
also take the remaining per-round budget, so the documented limit
still holds?

Thank you!

Best regards, Andrey Borodin.

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Alexandre Felipe 2026-09-14 18:34:33 Re: Restructured Shared Buffer Hash Table
Previous Message Peter Geoghegan 2026-09-14 18:08:17 Re: index prefetching