Thread

  1. Re: Optimize LISTEN/NOTIFY

    Joel Jacobson <joel@compiler.org> — 2025-11-12T20:37:51Z

    On Wed, Nov 12, 2025, at 17:57, Arseniy Mukhin wrote:
    > On Tue, Nov 11, 2025 at 7:35 PM Joel Jacobson <joel@compiler.org> wrote:
    >> I'm therefore attaching v24 again, but renamed to v26.
    >
    > Thank you for the new version!
    
    Thanks for reviewing!
    
    > I read direct advancement part of v26, one point about it:
    >
    > The comment in SignalBackend says:
    >
    >            * Listening backends that are not advancing and are stationary at
    >            * a position somewhere in the range we just wrote, can safely be
    >            * direct advanced to the new queue head, since we know that they
    >            * are not interested in our messages.
    >            */
    >
    > IIUC it's impossible for the listener to stop somewhere in between
    > queueHeadBeforeWrite and queueHeadAfterWrite. If the listener has
    > managed to read the first notification from the notifier, it means the
    > notifier transaction is complete and the listener should stop only
    > after reading all notifications (so we should always see pos =
    > queueHeadAfterWrite or further).
    
    Here is what I think can happen:
    
    If the notifications written by the notifier fills the current page,
    it updates QUEUE_HEAD, and if a listening backend then
    enters asyncQueueReadAllNotifications at this time,
    it will set its local `head` variable to the current QUEUE_HEAD,
    and when the notifier continues filling the next page,
    it will again update QUEUE_HEAD, and PreCommit_Notify
    will overwrite queueHeadAfterWrite with the QUEUE_HEAD.
    
    Sequence of events:
    
    1. In the notifier, PreCommit_Notify calls asyncQueueAddEntries,
    which updates QUEUE_HEAD when the page is full,
    (and sets queueHeadAfterWrite to this value).
    
    2. At this time, a listener wakes up and asyncQueueAddEntries
    reads the current QUEUE_HEAD value and stores it
    in its local `head` variable, and starts reading up to this pos.
    
    3. In the notifier, PreCommit_Notify calls asyncQueueAddEntries
    the second time, which updates QUEUE_HEAD,
    and sets queueHeadAfterWrite to the final value
    before returning.
    
    For this reason, I think the listener could actually stop
    in between queueHeadBeforeWrite and queueHeadAfterWrite,
    since it's local `head` variable could get the intermediary
    QUEUE_HEAD value, when a page is full.
    
    /Joel