> On 30 Jul 2024, at 14:05, Tomas Vondra <tomas.von...@enterprisedb.com> wrote:
> 
> 
> 
> On 7/26/24 14:13, Andrey M. Borodin wrote:
>> 
>> 
>>> On 26 Jul 2024, at 14:30, Andreas Karlsson <andr...@proxel.se> wrote:
>>> 
>>> I feel the tricky part about doing that is that we need to make sure the 
>>> fake LSNs are all less than the current real LSN when the index build 
>>> completes and while that normally should be the case we will have a almost 
>>> never exercised code path for when the fake LSN becomes bigger than the 
>>> real LSN which may contain bugs. Is that really worth it to optimize.
>>> 
>>> But if we are going to use fake LSN: since the index being built is not 
>>> visible to any scans we do not have to use GetFakeLSNForUnloggedRel() but 
>>> could use an own counter in shared memory in the GISTShared struct for this 
>>> specific index which starts at FirstNormalUnloggedLSN. This would give us 
>>> slightly less contention plus decrease the risk (for good and bad) of the 
>>> fake LSN being larger than the real LSN.
>> 
>> +1 for atomic counter in GISTShared.
> 
> I tried implementing this, see the attached 0002 patch that replaces the
> fake LSN with an atomic counter in shared memory. It seems to work (more
> testing needed), but I can't say I'm very happy with the code :-(

I agree. Passing this pointer everywhere seems ugly.

> 
> The way it passes the shared counter to places that actually need it is
> pretty ugly. The thing is - the counter needs to be in shared memory,
> but places like gistplacetopage() have no idea/need of that. I chose to
> simply pass a pg_atomic_uint64 pointer, but that's ... not pretty. Is
> there's a better way to do this?
> 
> I thought maybe we could simply increment the counter before each call
> and pass the LSN value - 64bits should be enough, not sure about the
> overhead. But gistplacetopage() also uses the LSN twice, and I'm not
> sure it'd be legal to use the same value twice.
> 
> Any better ideas?

How about global pointer to fake LSN?
Just set it to correct pointer when in parallel build, or NULL either way.

>> BTW we can just reset LSNs to GistBuildLSN just before doing 
>> log_newpage_range().
>> 
> 
> Why would the reset be necessary? Doesn't log_newpage_range() set page
> LSN to current insert LSN? So why would reset that?
> 
> I'm not sure about the discussion about NSN and the need to handle the
> case when NSN / fake LSN values get ahead of LSN. Is that really a
> problem? If the values generated from the counter are private to the
> index build, and log_newpage_range() replaces them with current LSN, do
> we still need to worry about it?

Stamping pages with new real LSN will do the trick. I didn’t know that 
log_newpage_range() is already doing so.

How do we synchronize Shared Fake LSN with global XLogCtl->unloggedLSN? Just 
bump XLogCtl->unloggedLSN if necessary?
Perhaps, consider using GetFakeLSNForUnloggedRel() instead of shared counter? 
As long as we do not care about FakeLSN>RealLSN.


Best regards, Andrey Borodin.

Reply via email to