Optimize LISTEN/NOTIFY
От | Joel Jacobson |
---|---|
Тема | Optimize LISTEN/NOTIFY |
Дата | |
Msg-id | 6899c044-4a82-49be-8117-e6f669765f7e@app.fastmail.com обсуждение исходный текст |
Ответы |
Re: Optimize LISTEN/NOTIFY
|
Список | pgsql-hackers |
Hi hackers, The current LISTEN/NOTIFY implementation is well-suited for use-cases like cache invalidation where many backends listen on the same channel. However, its scalability is limited when many backends listen on distinct channels. The root of the problem is that Async_Notify must signal every listening backend in the database, as it lacks central knowledge of which backend is interested in which channel. This results in an O(N) number of kill(pid, SIGUSR1) syscalls as the listener count grows. The attached proof-of-concept patch proposes a straightforward optimization for the single-listener case. It introduces a shared-memory hash table mapping (dboid, channelname) to the ProcNumber of a single listener. When NOTIFY is issued, we first check this table. If a single listener is found, we signal only that backend. Otherwise, we fall back to the existing broadcast behavior. The performance impact for this pattern is significant. A benchmark [1] measuring a NOTIFY "ping-pong" between two connections, while adding a variable number of idle listeners, shows the following: master (8893c3a): 0 extra listeners: 9126 TPS 10 extra listeners: 6233 TPS 100 extra listeners: 2020 TPS 1000 extra listeners: 238 TPS 0001-Optimize-LISTEN-NOTIFY-signaling-for-single-listener.patch: 0 extra listeners: 9152 TPS 10 extra listeners: 9352 TPS 100 extra listeners: 9320 TPS 1000 extra listeners: 8937 TPS As you can see, the patched version's performance is near O(1) with respect to the number of idle listeners, while the current implementation shows the expected O(N) degradation. This patch is a first-step. It uses a simple boolean has_multiple_listeners flag in the hash entry. Once a channel gets a second listener, this flag is set and, crucially, never cleared. The entry will then permanently indicate "multiple listeners", even after all backends on that channel disconnect. A more complete solution would likely use reference counting for each channel's listeners. This would solve the "stuck entry" problem and could also enable a further optimization: targeted signaling to all listeners of a multi-user channel, avoiding the database-wide broadcast entirely. The patch also includes a "wake only tail" optimization (contributed by Marko Tikkaja) to help prevent backends from falling too far behind. Instead of waking all lagging backends at once and creating a "thundering herd", this logic signals only the single backend that is currently at the queue tail. This ensures the global queue tail can always advance, relying on a chain reaction to get backends caught up efficiently. This seems like a sensible improvement in its own right. Thoughts? /Joel [1] Benchmark tool and full results: https://github.com/joelonsql/pg-bench-listen-notify
Вложения
В списке pgsql-hackers по дате отправления: