Re: BgBufferSync(): clarification about reusable_buffers variable

From: Ashutosh Bapat <ashutosh(dot)bapat(dot)oss(at)gmail(dot)com>
To: M vd H <mvdholst(at)gmail(dot)com>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: BgBufferSync(): clarification about reusable_buffers variable
Date: 2025-02-21 05:47:45
Message-ID: CAExHW5sFsiBOf=q3k2XmD5Dq0w+GhK-hriq-Q4AVRgwunfbRQg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Marcel,

On Sat, Feb 8, 2025 at 6:24 AM M vd H <mvdholst(at)gmail(dot)com> wrote:
>
> I have been reading the source code of the BgWriter, and there is some
> code in BgBufferSync() that I don't fully understand.
>
> In BgBufferSync(), we have the following code:
>
> while (num_to_scan > 0 && reusable_buffers < upcoming_alloc_est)
> {
> int sync_state = SyncOneBuffer(next_to_clean, true,
> wb_context);
>
> if (++next_to_clean >= NBuffers)
> {
> next_to_clean = 0;
> next_passes++;
> }
> num_to_scan--;
>
> if (sync_state & BUF_WRITTEN)
> {
> reusable_buffers++;
> if (++num_written >= bgwriter_lru_maxpages)
> {
> PendingBgWriterStats.maxwritten_clean++;
> break;
> }
> }
> else if (sync_state & BUF_REUSABLE)
> reusable_buffers++;
> }
>
>
> In SyncOneBuffer(), we lock the bufHdr and then check if both the
> refcount and usage_count are zero. If so, we mark the return value as
> BUF_REUSABLE.
> My understanding is that this means that the buffer could be reused
> when am empty shared buffer is needed by a backend. However, in the
> code above, we seem to track these in the reusable_buffers variable.
> But that variable is always incremented when the buffer was written in
> SyncOneBuffer() even though that buffer might have a non-zero refcount
> or non-zero usage_count.

I also think tha reusable_buffers keep track of the number of reusable
buffers. BgBufferSync() calls SyncOneBuffer() with skip_recently_used
= true. In that case, if SyncOneBuffer() finds the buffer with
refcount or usage_count non-zero, it just unlocks the header and
returns. Hence when called from BgBufferSync(), SyncOneBuffer() would
write a buffer only when it is not used. Hence the result would be 0
or BUF_REUSABLE or BUF_REUSABLE | BUF_WRITTEN. It can never be just
BUF_WRITTEN.

I guess, a patch like the one attached will be more readable and clear.

I ran pgbench for 5 minutes with this patch applied and didn't see the
Assert failing. But I don't think that's a good enough test to cover
all scenarios.

--
Best Wishes,
Ashutosh Bapat

Attachment Content-Type Size
bg_buffer_sync_clarity.patch application/x-patch 713 bytes

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2025-02-21 06:04:39 Re: generic plans and "initial" pruning
Previous Message Thomas Munro 2025-02-21 05:35:34 Re: GetRelationPath() vs critical sections