Re: LogwrtResult contended spinlock
Anastasia Lubennikova <a.lubennikova@postgrespro.ru>
From: Anastasia Lubennikova <a.lubennikova@postgrespro.ru>
To: Andres Freund <andres@anarazel.de>,
Alvaro Herrera <alvherre@2ndquadrant.com>
Cc: pgsql-hackers@lists.postgresql.org,
Jaime Casanova <jaime.casanova@2ndquadrant.com>
Date: 2020-11-24T10:36:58Z
Lists: pgsql-hackers
On 04.09.2020 20:13, Andres Freund wrote:
> Hi,
>
> On 2020-09-04 10:05:45 -0700, Andres Freund wrote:
>> On 2020-09-03 14:34:52 -0400, Alvaro Herrera wrote:
>>> Looking at patterns like this
>>>
>>> if (XLogCtl->LogwrtRqst.Write < EndPos)
>>> XLogCtl->LogwrtRqst.Write = EndPos;
>>>
>>> It seems possible to implement with
>>>
>>> do {
>>> XLogRecPtr currwrite;
>>>
>>> currwrite = pg_atomic_read_u64(LogwrtRqst.Write);
>>> if (currwrite > EndPos)
>>> break; // already done by somebody else
>>> if (pg_atomic_compare_exchange_u64(LogwrtRqst.Write,
>>> currwrite, EndPos))
>>> break; // successfully updated
>>> } while (true);
>>>
>>> This assumes that LogwrtRqst.Write never goes backwards, so it doesn't
>>> seem good material for a general routine.
>>>
>>> This *seems* correct to me, though this is muddy territory to me. Also,
>>> are there better ways to go about this?
>> Hm, I was thinking that we'd first go for reading it without a spinlock,
>> but continuing to write it as we currently do.
>>
>> But yea, I can't see an issue with what you propose here. I personally
>> find do {} while () weird and avoid it when not explicitly useful, but
>> that's extremely minor, obviously.
> Re general routine: On second thought, it might actually be worth having
> it. Even just for LSNs - there's plenty places where it's useful to
> ensure a variable is at least a certain size. I think I would be in
> favor of a general helper function.
Do you mean by general helper function something like this?
void
swap_lsn(XLogRecPtr old_value, XLogRecPtr new_value, bool to_largest)
{
while (true) {
XLogRecPtr currwrite;
currwrite = pg_atomic_read_u64(old_value);
if (to_largest)
if (currwrite > new_value)
break; /* already done by somebody else */
else
if (currwrite < new_value)
break; /* already done by somebody else */
if (pg_atomic_compare_exchange_u64(old_value,
currwrite, new_value))
break; /* already done by somebody else */
}
}
which will be called like
swap_lsn(XLogCtl->LogwrtRqst.Write, EndPos, true);
>
> Greetings,
>
> Andres Freund
This CF entry was inactive for a while. Alvaro, are you going to
continue working on it?
--
Anastasia Lubennikova
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
Commits
-
Remove bogus assertion in pg_atomic_monotonic_advance_u64
- 768f0c3e21b3 18.0 landed
- 3a9d0d774d90 17.0 landed
-
Add XLogCtl->logInsertResult
- f3ff7bf83bce 17.0 cited
-
Operate XLogCtl->log{Write,Flush}Result with atomics
- ee1cbe806dad 17.0 landed
-
Split XLogCtl->LogwrtResult into separate struct members
- c9920a9068ea 17.0 landed
-
Introduce atomic read/write functions with full barrier semantics.
- bd5132db558b 17.0 cited
-
Reduce the number of GetFlushRecPtr() calls done by walsenders.
- e369f3708636 13.0 cited
-
Remove most volatile qualifiers from xlog.c
- 6ba4ecbf477e 9.5.0 cited