• Tom Lane's avatar
    Rethink MemoryContext creation to improve performance. · 9fa6f00b
    Tom Lane authored
    This patch makes a number of interrelated changes to reduce the overhead
    involved in creating/deleting memory contexts.  The key ideas are:
    
    * Include the AllocSetContext header of an aset.c context in its first
    malloc request, rather than allocating it separately in TopMemoryContext.
    This means that we now always create an initial or "keeper" block in an
    aset, even if it never receives any allocation requests.
    
    * Create freelists in which we can save and recycle recently-destroyed
    asets (this idea is due to Robert Haas).
    
    * In the common case where the name of a context is a constant string,
    just store a pointer to it in the context header, rather than copying
    the string.
    
    The first change eliminates a palloc/pfree cycle per context, and
    also avoids bloat in TopMemoryContext, at the price that creating
    a context now involves a malloc/free cycle even if the context never
    receives any allocations.  That would be a loser for some common
    usage patterns, but recycling short-lived contexts via the freelist
    eliminates that pain.
    
    Avoiding copying constant strings not only saves strlen() and strcpy()
    overhead, but is an essential part of the freelist optimization because
    it makes the context header size constant.  Currently we make no
    attempt to use the freelist for contexts with non-constant names.
    (Perhaps someday we'll need to think harder about that, but in current
    usage, most contexts with custom names are long-lived anyway.)
    
    The freelist management in this initial commit is pretty simplistic,
    and we might want to refine it later --- but in common workloads that
    will never matter because the freelists will never get full anyway.
    
    To create a context with a non-constant name, one is now required to
    call AllocSetContextCreateExtended and specify the MEMCONTEXT_COPY_NAME
    option.  AllocSetContextCreate becomes a wrapper macro, and it includes
    a test that will complain about non-string-literal context name
    parameters on gcc and similar compilers.
    
    An unfortunate side effect of making AllocSetContextCreate a macro is
    that one is now *required* to use the size parameter abstraction macros
    (ALLOCSET_DEFAULT_SIZES and friends) with it; the pre-9.6 habit of
    writing out individual size parameters no longer works unless you
    switch to AllocSetContextCreateExtended.
    
    Internally to the memory-context-related modules, the context creation
    APIs are simplified, removing the rather baroque original design whereby
    a context-type module called mcxt.c which then called back into the
    context-type module.  That saved a bit of code duplication, but not much,
    and it prevented context-type modules from exercising control over the
    allocation of context headers.
    
    In passing, I converted the test-and-elog validation of aset size
    parameters into Asserts to save a few more cycles.  The original thought
    was that callers might compute size parameters on the fly, but in practice
    nobody does that, so it's useless to expend cycles on checking those
    numbers in production builds.
    
    Also, mark the memory context method-pointer structs "const",
    just for cleanliness.
    
    Discussion: https://postgr.es/m/2264.1512870796@sss.pgh.pa.us
    9fa6f00b
subscriptioncmds.c 30.7 KB