Re: Checkpointer write combining

From: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
To: Melanie Plageman <melanieplageman(at)gmail(dot)com>
Cc: 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>
Subject: Re: Checkpointer write combining
Date: 2025-09-12 03:33:17
Message-ID: 3FC2442D-1012-4079-A009-A0B8C45E092D@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On Sep 12, 2025, at 07:11, Melanie Plageman <melanieplageman(at)gmail(dot)com> wrote:
>
> On Wed, Sep 10, 2025 at 4:24 AM Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com> wrote:
>>
>
> Thanks for the review!
>
> For any of your feedback that I simply implemented, I omitted an
> inline comment about it. Those changes are included in the attached
> v6. My inline replies below are only for feedback requiring more
> discussion.
>
>> On Sep 10, 2025, at 01:55, Melanie Plageman <melanieplageman(at)gmail(dot)com> wrote:
>>
>> 2 - 0001
>> ```
>> --- a/src/backend/storage/buffer/freelist.c
>> +++ b/src/backend/storage/buffer/freelist.c
>>
>> + if (XLogNeedsFlush(lsn))
>> + {
>> + /*
>> + * Remove the dirty buffer from the ring; necessary to prevent an
>> + * infinite loop if all ring members are dirty.
>> + */
>> + strategy->buffers[strategy->current] = InvalidBuffer;
>> + return true;
>> + }
>>
>> - return true;
>> + return false;
>> }
>> ```
>>
>> We can do:
>> ```
>> If (!XLogNeedsFlush(lan))
>> Return false
>>
>> /* Remove the dirty buffer ….
>> */
>> Return true;
>> }
>> ```
>
> This would make the order of evaluation the same as master but I
> actually prefer it this way because then we only take the buffer
> header spinlock if there is a chance we will reject the buffer (e.g.
> we don't need to examine it for strategies except BAS_BULKREAD)
>
>

I don’t understand why the two versions are different:

if (XLogNeedsFlush(lsn))
{
/*
* Remove the dirty buffer from the ring; necessary to prevent an
* infinite loop if all ring members are dirty.
*/
strategy->buffers[strategy->current] = InvalidBuffer;
return true;
}

return false;

VS

if (XLogNeedsFlush(lsn))
return false;

/*
* Remove the dirty buffer from the ring; necessary to prevent an
* infinite loop if all ring members are dirty.
*/
strategy->buffers[strategy->current] = InvalidBuffer;
return true;

>
>> 10 - 0004
>> ```
>> --- a/src/backend/storage/buffer/bufmgr.c
>> +++ b/src/backend/storage/buffer/bufmgr.c
>>
>> + limit = Min(max_batch_size, limit);
>> ```
>>
>> Do we need to check max_batch_size should be less than (MAX_IO_COMBINE_LIMIT-1)? Because BufWriteBatch.bufdescs is defined with length of MAX_IO_COMBINE_LIMIT, and the first place has been used to store “start”.
>
> I assert that in StrategyMaxWriteBatchSize(). io_combine_limit is not
> allowed to exceed MAX_IO_COMBINE_LIMIT, so it shouldn't happen anyway,
> since we are capping ourselves at io_combine_limit. Or is that your
> point?
>

Please ignore comment 10. I think I cross-line it in my original email. I added the comment, then lately I found you have checked MAX_IO_COMBINE_LIMIT in the other function, so tried to delete it by cross-lining the comment.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message shveta malik 2025-09-12 03:42:36 Re: Clear logical slot's 'synced' flag on promotion of standby
Previous Message Naga Appani 2025-09-12 03:32:59 Re: [Proposal] Expose internal MultiXact member count function for efficient monitoring