Thread

  1. Re: Bound memory usage during manual slot sync retries

    Xuneng Zhou <xunengzhou@gmail.com> — 2026-05-15T13:20:01Z

    Hi Amit,
    
    On Fri, May 15, 2026 at 5:23 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Fri, May 15, 2026 at 11:02 AM Xuneng Zhou <xunengzhou@gmail.com> wrote:
    > >
    > > pg_sync_replication_slots() now retries inside a single SQL function
    > > call.  Unlike the slotsync worker, it does not get a transaction boundary
    > > between retry cycles, so allocations made while fetching and synchronizing
    > > remote slots can accumulate until the function returns.
    > >
    > > The existing list_free_deep(remote_slots) is not enough to bound this.
    > > It frees the List cells and the RemoteSlot structs stored as list
    > > elements, but it does not recursively free allocations owned by those
    > > structs, such as the copied slot name, plugin name, and database name.
    > >
    >
    > Right.
    >
    > > It also does not release unrelated per-cycle allocations made while
    > > fetching and processing the remote slots.
    > >
    >
    > BTW, did you notice via test or otherwise, what and how much other
    > unrelated memory is being allocated during each sync cycle if we
    > manually free the allocations you observed? This is mainly to learn
    > the impact of not doing all these allocations in some short-duration
    > memory context.
    
    I noticed this by reading the feature code while walking through the
    PG 19 release notes, not by observing actual memory growth in a
    running system. Besides the RemoteSlot field strings, there seems to
    be a few smaller per-cycle allocations that also accumulate:
    quote_literal_cstr() strings used to build the filtered query, a
    temporary TextDatumGetCString() result for invalidation_reason, the
    standalone TupleTableSlot in fetch_remote_slots(), and the list
    container built by get_local_synced_slots(). I chose a per-cycle
    memory context over manual pfrees to make the retry-cycle lifetime
    explicit and avoid maintaining a destructor for every current and
    future allocation in this path. It may be worth measuring how much
    extra memory actually accumulates during an extended wait to confirm
    the practical impact.
    
    -- 
    Regards,
    Xuneng Zhou
    HighGo Software Co., Ltd.