Thread

  1. Re: Optimize LISTEN/NOTIFY

    Joel Jacobson <joel@compiler.org> — 2025-11-13T06:28:03Z

    On Wed, Nov 12, 2025, at 17:57, Arseniy Mukhin wrote:
    > 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).
    >
    > So If I haven't missed anything, I think we can use QUEUE_POS_EQUAL as
    > direct advancement condition:
    >
    >     if (!QUEUE_BACKEND_IS_ADVANCING(i) && QUEUE_POS_EQUAL(pos,
    > queueHeadBeforeWrite))
    >     {
    >            QUEUE_BACKEND_POS(i) = queueHeadAfterWrite;
    >     }
    
    I added some logging just to test the hypothesis:
    
    @@ -2072,6 +2082,12 @@ SignalBackends(void)
                {
                    Assert(!QUEUE_POS_PRECEDES(pos, queueHeadBeforeWrite));
    
    +               if (!QUEUE_POS_EQUAL(pos, queueHeadBeforeWrite))
    +                   elog(LOG, "Direct advancement: PID %d from pos (%lld,%d) to queueHeadAfterWrite (%lld,%d)",
    +                        pid,
    +                        (long long) QUEUE_POS_PAGE(pos), QUEUE_POS_OFFSET(pos),
    +                        (long long) QUEUE_POS_PAGE(queueHeadAfterWrite), QUEUE_POS_OFFSET(queueHeadAfterWrite));
    +
                    QUEUE_BACKEND_POS(i) = queueHeadAfterWrite;
                }
            }
    
    And I'm getting a lot of such log entries when benchmarking
    `./pg_async_notify_test --listeners 1 --notifiers 1 --channels 50`
    
    I think this confirms that listeners can actually stop somewhere in between
    queueHeadBeforeWrite and queueHeadAfterWrite.
    
    /Joel