• Tom Lane's avatar
    Use a hash table to de-duplicate NOTIFY events faster. · bb5ae8f6
    Tom Lane authored
    Previously, async.c got rid of duplicate notifications by scanning
    the list of pending events to compare each one to the proposed new
    event.  This works okay for very small numbers of distinct events,
    but degrades as O(N^2) for many events.  We can improve matters by
    using a hash table to probe for duplicates.  So as not to add a
    lot of overhead for the simple cases that the code did handle well
    before, create the hash table only once a (sub)transaction has
    queued more than 16 distinct notify events.
    
    A downside is that we now have to do per-event work to propagate
    a successful subtransaction's notify events up to its parent.
    (But this isn't significant unless the subtransaction had many
    events, in which case the O(N^2) behavior would have been in
    play already, so we still come out ahead.)
    
    We can make some lemonade out of this lemon, though: since we must
    examine each event anyway, it's now possible to de-duplicate events
    fully, rather than skipping that for events merged up from
    subtransactions.  Hence, remove the old weasel wording in notify.sgml
    about whether de-duplication happens or not, and adjust the test
    case in async-notify.spec that exhibited the old behavior.
    
    While at it, rearrange the definition of struct Notification to make
    it more compact and require just one palloc per event, rather than
    two or three.  This saves space when there are a lot of events,
    in fact more than enough to buy back the space needed for the hash
    table.
    
    Patch by me, based on discussions around a different patch
    submitted by Filip Rembiałkowski.
    
    Discussion: https://postgr.es/m/17822.1564186806@sss.pgh.pa.us
    bb5ae8f6
async.c 69.6 KB