]> granicus.if.org Git - postgresql/commitdiff
Allow memory contexts to have both fixed and variable ident strings.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 27 Mar 2018 20:46:47 +0000 (16:46 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 27 Mar 2018 20:46:51 +0000 (16:46 -0400)
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident".  The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to.  The "ident" string, if
wanted, is supplied later.  This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.

The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there.  And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.

All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead.  This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other.  Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.

I also arranged for plancache contexts to use the query source string
as their identifier.  This is basically free for CachedPlanSources, as
they contained a copy of that string already.  We pay an extra pstrdup
to do it for CachedPlans.  That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first).  I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.

This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format.  This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.

The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1.  Seems
better for extension authors to endure just one round of API changes
not two.

Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com

20 files changed:
src/backend/access/transam/xact.c
src/backend/catalog/partition.c
src/backend/commands/policy.c
src/backend/executor/functions.c
src/backend/replication/logical/reorderbuffer.c
src/backend/statistics/extended_stats.c
src/backend/utils/cache/plancache.c
src/backend/utils/cache/relcache.c
src/backend/utils/cache/ts_cache.c
src/backend/utils/hash/dynahash.c
src/backend/utils/mmgr/aset.c
src/backend/utils/mmgr/generation.c
src/backend/utils/mmgr/mcxt.c
src/backend/utils/mmgr/slab.c
src/include/nodes/memnodes.h
src/include/utils/memutils.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_comp.c
src/pl/plpython/plpy_procedure.c
src/pl/tcl/pltcl.c

index 5d1b9027cf56c55ab100c8e3247766d431db85c7..cfc62011b506d6df780d4f75fdaede7643bd91b9 100644 (file)
@@ -999,7 +999,6 @@ AtStart_Memory(void)
                TransactionAbortContext =
                        AllocSetContextCreateExtended(TopMemoryContext,
                                                                                  "TransactionAbortContext",
-                                                                                 0,
                                                                                  32 * 1024,
                                                                                  32 * 1024,
                                                                                  32 * 1024);
index b00a986432e08e4e033d9ac36ac868e458b689a2..39ee773d93459305dcbc30764a378bd5729bff18 100644 (file)
@@ -525,10 +525,11 @@ RelationBuildPartitionDesc(Relation rel)
        }
 
        /* Now build the actual relcache partition descriptor */
-       rel->rd_pdcxt = AllocSetContextCreateExtended(CacheMemoryContext,
-                                                                                                 RelationGetRelationName(rel),
-                                                                                                 MEMCONTEXT_COPY_NAME,
-                                                                                                 ALLOCSET_DEFAULT_SIZES);
+       rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
+                                                                                 "partition descriptor",
+                                                                                 ALLOCSET_DEFAULT_SIZES);
+       MemoryContextCopySetIdentifier(rel->rd_pdcxt, RelationGetRelationName(rel));
+
        oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
 
        result = (PartitionDescData *) palloc0(sizeof(PartitionDescData));
index 280a14a101b52fc1ed7d34c0a96d8ac6cec76914..cfaf32ccbd7bebc14e555160db6a516bd8ec3160 100644 (file)
@@ -214,6 +214,9 @@ RelationBuildRowSecurity(Relation relation)
                SysScanDesc sscan;
                HeapTuple       tuple;
 
+               MemoryContextCopySetIdentifier(rscxt,
+                                                                          RelationGetRelationName(relation));
+
                rsdesc = MemoryContextAllocZero(rscxt, sizeof(RowSecurityDesc));
                rsdesc->rscxt = rscxt;
 
index 1c00ac9588f61adcde3e8c55a881ab8b0eb7c8ac..23545896d4dd89e039fd4e4b4a3f874bb662daf7 100644 (file)
@@ -612,7 +612,7 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
         * must be a child of whatever context holds the FmgrInfo.
         */
        fcontext = AllocSetContextCreate(finfo->fn_mcxt,
-                                                                        "SQL function data",
+                                                                        "SQL function",
                                                                         ALLOCSET_DEFAULT_SIZES);
 
        oldcontext = MemoryContextSwitchTo(fcontext);
@@ -635,9 +635,11 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
        procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
 
        /*
-        * copy function name immediately for use by error reporting callback
+        * copy function name immediately for use by error reporting callback, and
+        * for use as memory context identifier
         */
        fcache->fname = pstrdup(NameStr(procedureStruct->proname));
+       MemoryContextSetIdentifier(fcontext, fcache->fname);
 
        /*
         * get the result type from the procedure tuple, and check for polymorphic
index 5ffe638b19ce844afb24eca0b4bf156a237c3c45..b4016ed52b076806913a040a4fff86f8ff4dd9d2 100644 (file)
@@ -243,19 +243,16 @@ ReorderBufferAllocate(void)
 
        buffer->change_context = SlabContextCreate(new_ctx,
                                                                                           "Change",
-                                                                                          0,
                                                                                           SLAB_DEFAULT_BLOCK_SIZE,
                                                                                           sizeof(ReorderBufferChange));
 
        buffer->txn_context = SlabContextCreate(new_ctx,
                                                                                        "TXN",
-                                                                                       0,
                                                                                        SLAB_DEFAULT_BLOCK_SIZE,
                                                                                        sizeof(ReorderBufferTXN));
 
        buffer->tup_context = GenerationContextCreate(new_ctx,
                                                                                                  "Tuples",
-                                                                                                 0,
                                                                                                  SLAB_LARGE_BLOCK_SIZE);
 
        hash_ctl.keysize = sizeof(TransactionId);
index d34d5c3d12e41a43ab93b9515c41301e024867b1..6c836f68a987d5f2fa84e8017b1a5fc0f740595f 100644 (file)
@@ -74,7 +74,8 @@ BuildRelationExtStatistics(Relation onerel, double totalrows,
        MemoryContext cxt;
        MemoryContext oldcxt;
 
-       cxt = AllocSetContextCreate(CurrentMemoryContext, "stats ext",
+       cxt = AllocSetContextCreate(CurrentMemoryContext,
+                                                               "BuildRelationExtStatistics",
                                                                ALLOCSET_DEFAULT_SIZES);
        oldcxt = MemoryContextSwitchTo(cxt);
 
index 8d7d8e04c9fbde2e32b9cdd943de3ee9d5213a83..85bb7b914a049256dd4b0cc602ea2f91eba68cd0 100644 (file)
@@ -180,6 +180,7 @@ CreateCachedPlan(RawStmt *raw_parse_tree,
        plansource->magic = CACHEDPLANSOURCE_MAGIC;
        plansource->raw_parse_tree = copyObject(raw_parse_tree);
        plansource->query_string = pstrdup(query_string);
+       MemoryContextSetIdentifier(source_context, plansource->query_string);
        plansource->commandTag = commandTag;
        plansource->param_types = NULL;
        plansource->num_params = 0;
@@ -951,6 +952,7 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
                plan_context = AllocSetContextCreate(CurrentMemoryContext,
                                                                                         "CachedPlan",
                                                                                         ALLOCSET_START_SMALL_SIZES);
+               MemoryContextCopySetIdentifier(plan_context, plansource->query_string);
 
                /*
                 * Copy plan into the new context.
@@ -1346,6 +1348,7 @@ CopyCachedPlan(CachedPlanSource *plansource)
        newsource->magic = CACHEDPLANSOURCE_MAGIC;
        newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
        newsource->query_string = pstrdup(plansource->query_string);
+       MemoryContextSetIdentifier(source_context, newsource->query_string);
        newsource->commandTag = plansource->commandTag;
        if (plansource->num_params > 0)
        {
index 465130244059431ddea751b05469bcb725521a3a..de502f9bc9ea4d6bd8ae52bb54e4d8a5bf467194 100644 (file)
@@ -675,11 +675,12 @@ RelationBuildRuleLock(Relation relation)
        /*
         * Make the private context.  Assume it'll not contain much data.
         */
-       rulescxt = AllocSetContextCreateExtended(CacheMemoryContext,
-                                                                                        RelationGetRelationName(relation),
-                                                                                        MEMCONTEXT_COPY_NAME,
-                                                                                        ALLOCSET_SMALL_SIZES);
+       rulescxt = AllocSetContextCreate(CacheMemoryContext,
+                                                                        "relation rules",
+                                                                        ALLOCSET_SMALL_SIZES);
        relation->rd_rulescxt = rulescxt;
+       MemoryContextCopySetIdentifier(rulescxt,
+                                                                  RelationGetRelationName(relation));
 
        /*
         * allocate an array to hold the rewrite rules (the array is extended if
@@ -852,10 +853,11 @@ RelationBuildPartitionKey(Relation relation)
        if (!HeapTupleIsValid(tuple))
                return;
 
-       partkeycxt = AllocSetContextCreateExtended(CurTransactionContext,
-                                                                                          RelationGetRelationName(relation),
-                                                                                          MEMCONTEXT_COPY_NAME,
-                                                                                          ALLOCSET_SMALL_SIZES);
+       partkeycxt = AllocSetContextCreate(CurTransactionContext,
+                                                                          "partition key",
+                                                                          ALLOCSET_SMALL_SIZES);
+       MemoryContextCopySetIdentifier(partkeycxt,
+                                                                  RelationGetRelationName(relation));
 
        key = (PartitionKey) MemoryContextAllocZero(partkeycxt,
                                                                                                sizeof(PartitionKeyData));
@@ -1533,11 +1535,12 @@ RelationInitIndexAccessInfo(Relation relation)
         * a context, and not just a couple of pallocs, is so that we won't leak
         * any subsidiary info attached to fmgr lookup records.
         */
-       indexcxt = AllocSetContextCreateExtended(CacheMemoryContext,
-                                                                                        RelationGetRelationName(relation),
-                                                                                        MEMCONTEXT_COPY_NAME,
-                                                                                        ALLOCSET_SMALL_SIZES);
+       indexcxt = AllocSetContextCreate(CacheMemoryContext,
+                                                                        "index info",
+                                                                        ALLOCSET_SMALL_SIZES);
        relation->rd_indexcxt = indexcxt;
+       MemoryContextCopySetIdentifier(indexcxt,
+                                                                  RelationGetRelationName(relation));
 
        /*
         * Now we can fetch the index AM's API struct
@@ -5603,12 +5606,12 @@ load_relcache_init_file(bool shared)
                         * prepare index info context --- parameters should match
                         * RelationInitIndexAccessInfo
                         */
-                       indexcxt =
-                               AllocSetContextCreateExtended(CacheMemoryContext,
-                                                                                         RelationGetRelationName(rel),
-                                                                                         MEMCONTEXT_COPY_NAME,
-                                                                                         ALLOCSET_SMALL_SIZES);
+                       indexcxt = AllocSetContextCreate(CacheMemoryContext,
+                                                                                        "index info",
+                                                                                        ALLOCSET_SMALL_SIZES);
                        rel->rd_indexcxt = indexcxt;
+                       MemoryContextCopySetIdentifier(indexcxt,
+                                                                                  RelationGetRelationName(rel));
 
                        /*
                         * Now we can fetch the index AM's API struct.  (We can't store
index 3d5c1941488a6af26d0200f0b1a6ef69a5dc39a1..97347780d3b79e5aae93283367bea44fbe6885fa 100644 (file)
@@ -294,16 +294,19 @@ lookup_ts_dictionary_cache(Oid dictId)
                        Assert(!found);         /* it wasn't there a moment ago */
 
                        /* Create private memory context the first time through */
-                       saveCtx = AllocSetContextCreateExtended(CacheMemoryContext,
-                                                                                                       NameStr(dict->dictname),
-                                                                                                       MEMCONTEXT_COPY_NAME,
-                                                                                                       ALLOCSET_SMALL_SIZES);
+                       saveCtx = AllocSetContextCreate(CacheMemoryContext,
+                                                                                       "TS dictionary",
+                                                                                       ALLOCSET_SMALL_SIZES);
+                       MemoryContextCopySetIdentifier(saveCtx, NameStr(dict->dictname));
                }
                else
                {
                        /* Clear the existing entry's private context */
                        saveCtx = entry->dictCtx;
-                       MemoryContextResetAndDeleteChildren(saveCtx);
+                       /* Don't let context's ident pointer dangle while we reset it */
+                       MemoryContextSetIdentifier(saveCtx, NULL);
+                       MemoryContextReset(saveCtx);
+                       MemoryContextCopySetIdentifier(saveCtx, NameStr(dict->dictname));
                }
 
                MemSet(entry, 0, sizeof(TSDictionaryCacheEntry));
index 5281cd54103111be9435ae58978e4b6dca598d0c..785e0faffb52fb50fc594738fc25e1cc36dfdb26 100644 (file)
@@ -340,11 +340,9 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
                        CurrentDynaHashCxt = info->hcxt;
                else
                        CurrentDynaHashCxt = TopMemoryContext;
-               CurrentDynaHashCxt =
-                       AllocSetContextCreateExtended(CurrentDynaHashCxt,
-                                                                                 tabname,
-                                                                                 MEMCONTEXT_COPY_NAME,
-                                                                                 ALLOCSET_DEFAULT_SIZES);
+               CurrentDynaHashCxt = AllocSetContextCreate(CurrentDynaHashCxt,
+                                                                                                  "dynahash",
+                                                                                                  ALLOCSET_DEFAULT_SIZES);
        }
 
        /* Initialize the hash header, plus a copy of the table name */
@@ -354,6 +352,10 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
        hashp->tabname = (char *) (hashp + 1);
        strcpy(hashp->tabname, tabname);
 
+       /* If we have a private context, label it with hashtable's name */
+       if (!(flags & HASH_SHARED_MEM))
+               MemoryContextSetIdentifier(CurrentDynaHashCxt, hashp->tabname);
+
        /*
         * Select the appropriate hash function (see comments at head of file).
         */
index 3f9b18844fa1fe5a107b0d7557f95072964ee90c..e3d2c4e2faa05168f7d75333669352ad2a994596 100644 (file)
@@ -130,7 +130,6 @@ typedef struct AllocSetContext
        Size            initBlockSize;  /* initial block size */
        Size            maxBlockSize;   /* maximum block size */
        Size            nextBlockSize;  /* next block size to allocate */
-       Size            headerSize;             /* allocated size of context header */
        Size            allocChunkLimit;        /* effective chunk size limit */
        AllocBlock      keeper;                 /* keep this block over resets */
        /* freelist this context could be put in, or -1 if not a candidate: */
@@ -228,10 +227,7 @@ typedef struct AllocChunkData
  * only its initial malloc chunk and no others.  To be a candidate for a
  * freelist, a context must have the same minContextSize/initBlockSize as
  * other contexts in the list; but its maxBlockSize is irrelevant since that
- * doesn't affect the size of the initial chunk.  Also, candidate contexts
- * *must not* use MEMCONTEXT_COPY_NAME since that would make their header size
- * variable.  (We currently insist that all flags be zero, since other flags
- * would likely make the contexts less interchangeable, too.)
+ * doesn't affect the size of the initial chunk.
  *
  * We currently provide one freelist for ALLOCSET_DEFAULT_SIZES contexts
  * and one for ALLOCSET_SMALL_SIZES contexts; the latter works for
@@ -276,7 +272,8 @@ static void AllocSetReset(MemoryContext context);
 static void AllocSetDelete(MemoryContext context);
 static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer);
 static bool AllocSetIsEmpty(MemoryContext context);
-static void AllocSetStats(MemoryContext context, int level, bool print,
+static void AllocSetStats(MemoryContext context,
+                         MemoryStatsPrintFunc printfunc, void *passthru,
                          MemoryContextCounters *totals);
 
 #ifdef MEMORY_CONTEXT_CHECKING
@@ -378,14 +375,11 @@ AllocSetFreeIndex(Size size)
  *             Create a new AllocSet context.
  *
  * parent: parent context, or NULL if top-level context
- * name: name of context (for debugging only, need not be unique)
- * flags: bitmask of MEMCONTEXT_XXX option flags
+ * name: name of context (must be statically allocated)
  * minContextSize: minimum context size
  * initBlockSize: initial allocation block size
  * maxBlockSize: maximum allocation block size
  *
- * Notes: if flags & MEMCONTEXT_COPY_NAME, the name string will be copied into
- * context-lifespan storage; otherwise, it had better be statically allocated.
  * Most callers should abstract the context size parameters using a macro
  * such as ALLOCSET_DEFAULT_SIZES.  (This is now *required* when going
  * through the AllocSetContextCreate macro.)
@@ -393,13 +387,11 @@ AllocSetFreeIndex(Size size)
 MemoryContext
 AllocSetContextCreateExtended(MemoryContext parent,
                                                          const char *name,
-                                                         int flags,
                                                          Size minContextSize,
                                                          Size initBlockSize,
                                                          Size maxBlockSize)
 {
        int                     freeListIndex;
-       Size            headerSize;
        Size            firstBlockSize;
        AllocSet        set;
        AllocBlock      block;
@@ -431,12 +423,10 @@ AllocSetContextCreateExtended(MemoryContext parent,
         * Check whether the parameters match either available freelist.  We do
         * not need to demand a match of maxBlockSize.
         */
-       if (flags == 0 &&
-               minContextSize == ALLOCSET_DEFAULT_MINSIZE &&
+       if (minContextSize == ALLOCSET_DEFAULT_MINSIZE &&
                initBlockSize == ALLOCSET_DEFAULT_INITSIZE)
                freeListIndex = 0;
-       else if (flags == 0 &&
-                        minContextSize == ALLOCSET_SMALL_MINSIZE &&
+       else if (minContextSize == ALLOCSET_SMALL_MINSIZE &&
                         initBlockSize == ALLOCSET_SMALL_INITSIZE)
                freeListIndex = 1;
        else
@@ -462,25 +452,17 @@ AllocSetContextCreateExtended(MemoryContext parent,
                        /* Reinitialize its header, installing correct name and parent */
                        MemoryContextCreate((MemoryContext) set,
                                                                T_AllocSetContext,
-                                                               set->headerSize,
-                                                               sizeof(AllocSetContext),
                                                                &AllocSetMethods,
                                                                parent,
-                                                               name,
-                                                               flags);
+                                                               name);
 
                        return (MemoryContext) set;
                }
        }
 
-       /* Size of the memory context header, including name storage if needed */
-       if (flags & MEMCONTEXT_COPY_NAME)
-               headerSize = MAXALIGN(sizeof(AllocSetContext) + strlen(name) + 1);
-       else
-               headerSize = MAXALIGN(sizeof(AllocSetContext));
-
        /* Determine size of initial block */
-       firstBlockSize = headerSize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+       firstBlockSize = MAXALIGN(sizeof(AllocSetContext)) +
+               ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
        if (minContextSize != 0)
                firstBlockSize = Max(firstBlockSize, minContextSize);
        else
@@ -508,7 +490,7 @@ AllocSetContextCreateExtended(MemoryContext parent,
         */
 
        /* Fill in the initial block's block header */
-       block = (AllocBlock) (((char *) set) + headerSize);
+       block = (AllocBlock) (((char *) set) + MAXALIGN(sizeof(AllocSetContext)));
        block->aset = set;
        block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
        block->endptr = ((char *) set) + firstBlockSize;
@@ -529,7 +511,6 @@ AllocSetContextCreateExtended(MemoryContext parent,
        set->initBlockSize = initBlockSize;
        set->maxBlockSize = maxBlockSize;
        set->nextBlockSize = initBlockSize;
-       set->headerSize = headerSize;
        set->freeListIndex = freeListIndex;
 
        /*
@@ -559,12 +540,9 @@ AllocSetContextCreateExtended(MemoryContext parent,
        /* Finally, do the type-independent part of context creation */
        MemoryContextCreate((MemoryContext) set,
                                                T_AllocSetContext,
-                                               headerSize,
-                                               sizeof(AllocSetContext),
                                                &AllocSetMethods,
                                                parent,
-                                               name,
-                                               flags);
+                                               name);
 
        return (MemoryContext) set;
 }
@@ -1327,12 +1305,13 @@ AllocSetIsEmpty(MemoryContext context)
  * AllocSetStats
  *             Compute stats about memory consumption of an allocset.
  *
- * level: recursion level (0 at top level); used for print indentation.
- * print: true to print stats to stderr.
- * totals: if not NULL, add stats about this allocset into *totals.
+ * printfunc: if not NULL, pass a human-readable stats string to this.
+ * passthru: pass this pointer through to printfunc.
+ * totals: if not NULL, add stats about this context into *totals.
  */
 static void
-AllocSetStats(MemoryContext context, int level, bool print,
+AllocSetStats(MemoryContext context,
+                         MemoryStatsPrintFunc printfunc, void *passthru,
                          MemoryContextCounters *totals)
 {
        AllocSet        set = (AllocSet) context;
@@ -1344,7 +1323,7 @@ AllocSetStats(MemoryContext context, int level, bool print,
        int                     fidx;
 
        /* Include context header in totalspace */
-       totalspace = set->headerSize;
+       totalspace = MAXALIGN(sizeof(AllocSetContext));
 
        for (block = set->blocks; block != NULL; block = block->next)
        {
@@ -1364,16 +1343,15 @@ AllocSetStats(MemoryContext context, int level, bool print,
                }
        }
 
-       if (print)
+       if (printfunc)
        {
-               int                     i;
-
-               for (i = 0; i < level; i++)
-                       fprintf(stderr, "  ");
-               fprintf(stderr,
-                               "%s: %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
-                               set->header.name, totalspace, nblocks, freespace, freechunks,
-                               totalspace - freespace);
+               char            stats_string[200];
+
+               snprintf(stats_string, sizeof(stats_string),
+                                "%zu total in %zd blocks; %zu free (%zd chunks); %zu used",
+                                totalspace, nblocks, freespace, freechunks,
+                                totalspace - freespace);
+               printfunc(context, passthru, stats_string);
        }
 
        if (totals)
index 338386a5d198e8fcfb5642c69e5f3b0b6a61e981..7ee3c481b346e1d1739b09145c33b2c09dbf2e1f 100644 (file)
@@ -61,7 +61,6 @@ typedef struct GenerationContext
 
        /* Generational context parameters */
        Size            blockSize;              /* standard block size */
-       Size            headerSize;             /* allocated size of context header */
 
        GenerationBlock *block;         /* current (most recently allocated) block */
        dlist_head      blocks;                 /* list of blocks */
@@ -154,7 +153,8 @@ static void GenerationReset(MemoryContext context);
 static void GenerationDelete(MemoryContext context);
 static Size GenerationGetChunkSpace(MemoryContext context, void *pointer);
 static bool GenerationIsEmpty(MemoryContext context);
-static void GenerationStats(MemoryContext context, int level, bool print,
+static void GenerationStats(MemoryContext context,
+                               MemoryStatsPrintFunc printfunc, void *passthru,
                                MemoryContextCounters *totals);
 
 #ifdef MEMORY_CONTEXT_CHECKING
@@ -203,14 +203,16 @@ static const MemoryContextMethods GenerationMethods = {
 /*
  * GenerationContextCreate
  *             Create a new Generation context.
+ *
+ * parent: parent context, or NULL if top-level context
+ * name: name of context (must be statically allocated)
+ * blockSize: generation block size
  */
 MemoryContext
 GenerationContextCreate(MemoryContext parent,
                                                const char *name,
-                                               int flags,
                                                Size blockSize)
 {
-       Size            headerSize;
        GenerationContext *set;
 
        /* Assert we padded GenerationChunk properly */
@@ -238,13 +240,7 @@ GenerationContextCreate(MemoryContext parent,
         * freeing the first generation of allocations.
         */
 
-       /* Size of the memory context header, including name storage if needed */
-       if (flags & MEMCONTEXT_COPY_NAME)
-               headerSize = MAXALIGN(sizeof(GenerationContext) + strlen(name) + 1);
-       else
-               headerSize = MAXALIGN(sizeof(GenerationContext));
-
-       set = (GenerationContext *) malloc(headerSize);
+       set = (GenerationContext *) malloc(MAXALIGN(sizeof(GenerationContext)));
        if (set == NULL)
        {
                MemoryContextStats(TopMemoryContext);
@@ -262,19 +258,15 @@ GenerationContextCreate(MemoryContext parent,
 
        /* Fill in GenerationContext-specific header fields */
        set->blockSize = blockSize;
-       set->headerSize = headerSize;
        set->block = NULL;
        dlist_init(&set->blocks);
 
        /* Finally, do the type-independent part of context creation */
        MemoryContextCreate((MemoryContext) set,
                                                T_GenerationContext,
-                                               headerSize,
-                                               sizeof(GenerationContext),
                                                &GenerationMethods,
                                                parent,
-                                               name,
-                                               flags);
+                                               name);
 
        return (MemoryContext) set;
 }
@@ -683,15 +675,16 @@ GenerationIsEmpty(MemoryContext context)
  * GenerationStats
  *             Compute stats about memory consumption of a Generation context.
  *
- * level: recursion level (0 at top level); used for print indentation.
- * print: true to print stats to stderr.
- * totals: if not NULL, add stats about this Generation into *totals.
+ * printfunc: if not NULL, pass a human-readable stats string to this.
+ * passthru: pass this pointer through to printfunc.
+ * totals: if not NULL, add stats about this context into *totals.
  *
  * XXX freespace only accounts for empty space at the end of the block, not
  * space of freed chunks (which is unknown).
  */
 static void
-GenerationStats(MemoryContext context, int level, bool print,
+GenerationStats(MemoryContext context,
+                               MemoryStatsPrintFunc printfunc, void *passthru,
                                MemoryContextCounters *totals)
 {
        GenerationContext *set = (GenerationContext *) context;
@@ -703,7 +696,7 @@ GenerationStats(MemoryContext context, int level, bool print,
        dlist_iter      iter;
 
        /* Include context header in totalspace */
-       totalspace = set->headerSize;
+       totalspace = MAXALIGN(sizeof(GenerationContext));
 
        dlist_foreach(iter, &set->blocks)
        {
@@ -716,16 +709,15 @@ GenerationStats(MemoryContext context, int level, bool print,
                freespace += (block->endptr - block->freeptr);
        }
 
-       if (print)
+       if (printfunc)
        {
-               int                     i;
-
-               for (i = 0; i < level; i++)
-                       fprintf(stderr, "  ");
-               fprintf(stderr,
-                               "Generation: %s: %zu total in %zd blocks (%zd chunks); %zu free (%zd chunks); %zu used\n",
-                               ((MemoryContext) set)->name, totalspace, nblocks, nchunks, freespace,
-                               nfreechunks, totalspace - freespace);
+               char            stats_string[200];
+
+               snprintf(stats_string, sizeof(stats_string),
+                                "%zu total in %zd blocks (%zd chunks); %zu free (%zd chunks); %zu used",
+                                totalspace, nblocks, nchunks, freespace,
+                                nfreechunks, totalspace - freespace);
+               printfunc(context, passthru, stats_string);
        }
 
        if (totals)
index d7baa54808fcee39a44175bc1d1138db2f1db178..6cda41481fb6d6f5d8ee144b804233c8ba6f8068 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "postgres.h"
 
+#include "mb/pg_wchar.h"
 #include "miscadmin.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
@@ -55,6 +56,8 @@ static void MemoryContextCallResetCallbacks(MemoryContext context);
 static void MemoryContextStatsInternal(MemoryContext context, int level,
                                                   bool print, int max_children,
                                                   MemoryContextCounters *totals);
+static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
+                                               const char *stats_string);
 
 /*
  * You should not do memory allocations within a critical section, because
@@ -118,7 +121,6 @@ MemoryContextInit(void)
         */
        ErrorContext = AllocSetContextCreateExtended(TopMemoryContext,
                                                                                                 "ErrorContext",
-                                                                                                0,
                                                                                                 8 * 1024,
                                                                                                 8 * 1024,
                                                                                                 8 * 1024);
@@ -158,6 +160,17 @@ MemoryContextResetOnly(MemoryContext context)
        if (!context->isReset)
        {
                MemoryContextCallResetCallbacks(context);
+
+               /*
+                * If context->ident points into the context's memory, it will become
+                * a dangling pointer.  We could prevent that by setting it to NULL
+                * here, but that would break valid coding patterns that keep the
+                * ident elsewhere, e.g. in a parent context.  Another idea is to use
+                * MemoryContextContains(), but we don't require ident strings to be
+                * in separately-palloc'd chunks, so that risks false positives.  So
+                * for now we assume the programmer got it right.
+                */
+
                context->methods->reset(context);
                context->isReset = true;
                VALGRIND_DESTROY_MEMPOOL(context);
@@ -222,6 +235,13 @@ MemoryContextDelete(MemoryContext context)
         */
        MemoryContextSetParent(context, NULL);
 
+       /*
+        * Also reset the context's ident pointer, in case it points into the
+        * context.  This would only matter if someone tries to get stats on the
+        * (already unlinked) context, which is unlikely, but let's be safe.
+        */
+       context->ident = NULL;
+
        context->methods->delete_context(context);
 
        VALGRIND_DESTROY_MEMPOOL(context);
@@ -295,6 +315,23 @@ MemoryContextCallResetCallbacks(MemoryContext context)
        }
 }
 
+/*
+ * MemoryContextSetIdentifier
+ *             Set the identifier string for a memory context.
+ *
+ * An identifier can be provided to help distinguish among different contexts
+ * of the same kind in memory context stats dumps.  The identifier string
+ * must live at least as long as the context it is for; typically it is
+ * allocated inside that context, so that it automatically goes away on
+ * context deletion.  Pass id = NULL to forget any old identifier.
+ */
+void
+MemoryContextSetIdentifier(MemoryContext context, const char *id)
+{
+       AssertArg(MemoryContextIsValid(context));
+       context->ident = id;
+}
+
 /*
  * MemoryContextSetParent
  *             Change a context to belong to a new parent (or no parent).
@@ -480,7 +517,10 @@ MemoryContextStatsInternal(MemoryContext context, int level,
        AssertArg(MemoryContextIsValid(context));
 
        /* Examine the context itself */
-       context->methods->stats(context, level, print, totals);
+       context->methods->stats(context,
+                                                       print ? MemoryContextStatsPrint : NULL,
+                                                       (void *) &level,
+                                                       totals);
 
        /*
         * Examine children.  If there are more than max_children of them, we do
@@ -531,6 +571,67 @@ MemoryContextStatsInternal(MemoryContext context, int level,
        }
 }
 
+/*
+ * MemoryContextStatsPrint
+ *             Print callback used by MemoryContextStatsInternal
+ *
+ * For now, the passthru pointer just points to "int level"; later we might
+ * make that more complicated.
+ */
+static void
+MemoryContextStatsPrint(MemoryContext context, void *passthru,
+                                               const char *stats_string)
+{
+       int                     level = *(int *) passthru;
+       const char *name = context->name;
+       const char *ident = context->ident;
+       int                     i;
+
+       /*
+        * It seems preferable to label dynahash contexts with just the hash table
+        * name.  Those are already unique enough, so the "dynahash" part isn't
+        * very helpful, and this way is more consistent with pre-v11 practice.
+        */
+       if (ident && strcmp(name, "dynahash") == 0)
+       {
+               name = ident;
+               ident = NULL;
+       }
+
+       for (i = 0; i < level; i++)
+               fprintf(stderr, "  ");
+       fprintf(stderr, "%s: %s", name, stats_string);
+       if (ident)
+       {
+               /*
+                * Some contexts may have very long identifiers (e.g., SQL queries).
+                * Arbitrarily truncate at 100 bytes, but be careful not to break
+                * multibyte characters.  Also, replace ASCII control characters, such
+                * as newlines, with spaces.
+                */
+               int                     idlen = strlen(ident);
+               bool            truncated = false;
+
+               if (idlen > 100)
+               {
+                       idlen = pg_mbcliplen(ident, idlen, 100);
+                       truncated = true;
+               }
+               fprintf(stderr, ": ");
+               while (idlen-- > 0)
+               {
+                       unsigned char c = *ident++;
+
+                       if (c < ' ')
+                               c = ' ';
+                       fputc(c, stderr);
+               }
+               if (truncated)
+                       fprintf(stderr, "...");
+       }
+       fputc('\n', stderr);
+}
+
 /*
  * MemoryContextCheck
  *             Check all chunks in the named context.
@@ -612,34 +713,23 @@ MemoryContextContains(MemoryContext context, void *pointer)
  *
  * node: the as-yet-uninitialized common part of the context header node.
  * tag: NodeTag code identifying the memory context type.
- * size: total size of context header including context-type-specific fields,
- *             as well as space for the context name if MEMCONTEXT_COPY_NAME is set.
- * nameoffset: where within the "size" space to insert the context name.
  * methods: context-type-specific methods (usually statically allocated).
  * parent: parent context, or NULL if this will be a top-level context.
- * name: name of context (for debugging only, need not be unique).
- * flags: bitmask of MEMCONTEXT_XXX option flags.
+ * name: name of context (must be statically allocated).
  *
  * Context routines generally assume that MemoryContextCreate can't fail,
  * so this can contain Assert but not elog/ereport.
  */
 void
 MemoryContextCreate(MemoryContext node,
-                                       NodeTag tag, Size size, Size nameoffset,
+                                       NodeTag tag,
                                        const MemoryContextMethods *methods,
                                        MemoryContext parent,
-                                       const char *name,
-                                       int flags)
+                                       const char *name)
 {
        /* Creating new memory contexts is not allowed in a critical section */
        Assert(CritSectionCount == 0);
 
-       /* Check size is sane */
-       Assert(nameoffset >= sizeof(MemoryContextData));
-       Assert((flags & MEMCONTEXT_COPY_NAME) ?
-                  size >= nameoffset + strlen(name) + 1 :
-                  size >= nameoffset);
-
        /* Initialize all standard fields of memory context header */
        node->type = tag;
        node->isReset = true;
@@ -647,22 +737,10 @@ MemoryContextCreate(MemoryContext node,
        node->parent = parent;
        node->firstchild = NULL;
        node->prevchild = NULL;
+       node->name = name;
+       node->ident = NULL;
        node->reset_cbs = NULL;
 
-       if (flags & MEMCONTEXT_COPY_NAME)
-       {
-               /* Insert context name into space reserved for it */
-               char       *namecopy = ((char *) node) + nameoffset;
-
-               node->name = namecopy;
-               strcpy(namecopy, name);
-       }
-       else
-       {
-               /* Assume the passed-in name is statically allocated */
-               node->name = name;
-       }
-
        /* OK to link node into context tree */
        if (parent)
        {
index 58beb64ab9cd41bffa2d1b0fa0a5daa3f375bb8d..26b0a156b6b2f22eee8feb14c72b2a366729be0b 100644 (file)
@@ -131,7 +131,8 @@ static void SlabReset(MemoryContext context);
 static void SlabDelete(MemoryContext context);
 static Size SlabGetChunkSpace(MemoryContext context, void *pointer);
 static bool SlabIsEmpty(MemoryContext context);
-static void SlabStats(MemoryContext context, int level, bool print,
+static void SlabStats(MemoryContext context,
+                 MemoryStatsPrintFunc printfunc, void *passthru,
                  MemoryContextCounters *totals);
 #ifdef MEMORY_CONTEXT_CHECKING
 static void SlabCheck(MemoryContext context);
@@ -176,27 +177,22 @@ static const MemoryContextMethods SlabMethods = {
  *             Create a new Slab context.
  *
  * parent: parent context, or NULL if top-level context
- * name: name of context (for debugging only, need not be unique)
- * flags: bitmask of MEMCONTEXT_XXX option flags
+ * name: name of context (must be statically allocated)
  * blockSize: allocation block size
  * chunkSize: allocation chunk size
  *
- * Notes: if flags & MEMCONTEXT_COPY_NAME, the name string will be copied into
- * context-lifespan storage; otherwise, it had better be statically allocated.
  * The chunkSize may not exceed:
  *             MAXALIGN_DOWN(SIZE_MAX) - MAXALIGN(sizeof(SlabBlock)) - SLAB_CHUNKHDRSZ
  */
 MemoryContext
 SlabContextCreate(MemoryContext parent,
                                  const char *name,
-                                 int flags,
                                  Size blockSize,
                                  Size chunkSize)
 {
        int                     chunksPerBlock;
        Size            fullChunkSize;
        Size            freelistSize;
-       Size            nameOffset;
        Size            headerSize;
        SlabContext *slab;
        int                     i;
@@ -231,12 +227,8 @@ SlabContextCreate(MemoryContext parent,
         * this with the first regular block; not worth the extra complication.
         */
 
-       /* Size of the memory context header, including name storage if needed */
-       nameOffset = offsetof(SlabContext, freelist) + freelistSize;
-       if (flags & MEMCONTEXT_COPY_NAME)
-               headerSize = nameOffset + strlen(name) + 1;
-       else
-               headerSize = nameOffset;
+       /* Size of the memory context header */
+       headerSize = offsetof(SlabContext, freelist) + freelistSize;
 
        slab = (SlabContext *) malloc(headerSize);
        if (slab == NULL)
@@ -270,12 +262,9 @@ SlabContextCreate(MemoryContext parent,
        /* Finally, do the type-independent part of context creation */
        MemoryContextCreate((MemoryContext) slab,
                                                T_SlabContext,
-                                               headerSize,
-                                               nameOffset,
                                                &SlabMethods,
                                                parent,
-                                               name,
-                                               flags);
+                                               name);
 
        return (MemoryContext) slab;
 }
@@ -634,12 +623,13 @@ SlabIsEmpty(MemoryContext context)
  * SlabStats
  *             Compute stats about memory consumption of a Slab context.
  *
- * level: recursion level (0 at top level); used for print indentation.
- * print: true to print stats to stderr.
- * totals: if not NULL, add stats about this Slab into *totals.
+ * printfunc: if not NULL, pass a human-readable stats string to this.
+ * passthru: pass this pointer through to printfunc.
+ * totals: if not NULL, add stats about this context into *totals.
  */
 static void
-SlabStats(MemoryContext context, int level, bool print,
+SlabStats(MemoryContext context,
+                 MemoryStatsPrintFunc printfunc, void *passthru,
                  MemoryContextCounters *totals)
 {
        SlabContext *slab = castNode(SlabContext, context);
@@ -667,14 +657,15 @@ SlabStats(MemoryContext context, int level, bool print,
                }
        }
 
-       if (print)
+       if (printfunc)
        {
-               for (i = 0; i < level; i++)
-                       fprintf(stderr, "  ");
-               fprintf(stderr,
-                               "Slab: %s: %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
-                               slab->header.name, totalspace, nblocks, freespace, freechunks,
-                               totalspace - freespace);
+               char            stats_string[200];
+
+               snprintf(stats_string, sizeof(stats_string),
+                                "%zu total in %zd blocks; %zu free (%zd chunks); %zu used",
+                                totalspace, nblocks, freespace, freechunks,
+                                totalspace - freespace);
+               printfunc(context, passthru, stats_string);
        }
 
        if (totals)
index ccb64f01a72915ffbc994aef9cc3942e1d68139d..2a8d83f3d08682915a6c008b69b572f9d64f2900 100644 (file)
@@ -39,18 +39,21 @@ typedef struct MemoryContextCounters
  *             A logical context in which memory allocations occur.
  *
  * MemoryContext itself is an abstract type that can have multiple
- * implementations, though for now we have only AllocSetContext.
+ * implementations.
  * The function pointers in MemoryContextMethods define one specific
  * implementation of MemoryContext --- they are a virtual function table
  * in C++ terms.
  *
  * Node types that are actual implementations of memory contexts must
- * begin with the same fields as MemoryContext.
+ * begin with the same fields as MemoryContextData.
  *
  * Note: for largely historical reasons, typedef MemoryContext is a pointer
  * to the context struct rather than the struct type itself.
  */
 
+typedef void (*MemoryStatsPrintFunc) (MemoryContext context, void *passthru,
+                                                                         const char *stats_string);
+
 typedef struct MemoryContextMethods
 {
        void       *(*alloc) (MemoryContext context, Size size);
@@ -61,7 +64,8 @@ typedef struct MemoryContextMethods
        void            (*delete_context) (MemoryContext context);
        Size            (*get_chunk_space) (MemoryContext context, void *pointer);
        bool            (*is_empty) (MemoryContext context);
-       void            (*stats) (MemoryContext context, int level, bool print,
+       void            (*stats) (MemoryContext context,
+                                                 MemoryStatsPrintFunc printfunc, void *passthru,
                                                  MemoryContextCounters *totals);
 #ifdef MEMORY_CONTEXT_CHECKING
        void            (*check) (MemoryContext context);
@@ -81,6 +85,7 @@ typedef struct MemoryContextData
        MemoryContext prevchild;        /* previous child of same parent */
        MemoryContext nextchild;        /* next child of same parent */
        const char *name;                       /* context name (just for debugging) */
+       const char *ident;                      /* context ID if any (just for debugging) */
        MemoryContextCallback *reset_cbs;       /* list of reset/delete callbacks */
 } MemoryContextData;
 
index 6e6c6f2e4cddd6354b55d7d9e7fa132fb27c827d..4f2ca26caf03c5169f3db3fd9b570c367849b7bb 100644 (file)
@@ -76,6 +76,7 @@ extern void MemoryContextDelete(MemoryContext context);
 extern void MemoryContextResetOnly(MemoryContext context);
 extern void MemoryContextResetChildren(MemoryContext context);
 extern void MemoryContextDeleteChildren(MemoryContext context);
+extern void MemoryContextSetIdentifier(MemoryContext context, const char *id);
 extern void MemoryContextSetParent(MemoryContext context,
                                           MemoryContext new_parent);
 extern Size GetMemoryChunkSpace(void *pointer);
@@ -91,6 +92,10 @@ extern void MemoryContextCheck(MemoryContext context);
 #endif
 extern bool MemoryContextContains(MemoryContext context, void *pointer);
 
+/* Handy macro for copying and assigning context ID ... but note double eval */
+#define MemoryContextCopySetIdentifier(cxt, id) \
+       MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id))
+
 /*
  * GetMemoryChunkContext
  *             Given a currently-allocated chunk, determine the context
@@ -133,11 +138,10 @@ GetMemoryChunkContext(void *pointer)
  * specific creation routines, and noplace else.
  */
 extern void MemoryContextCreate(MemoryContext node,
-                                       NodeTag tag, Size size, Size nameoffset,
+                                       NodeTag tag,
                                        const MemoryContextMethods *methods,
                                        MemoryContext parent,
-                                       const char *name,
-                                       int flags);
+                                       const char *name);
 
 
 /*
@@ -147,46 +151,37 @@ extern void MemoryContextCreate(MemoryContext node,
 /* aset.c */
 extern MemoryContext AllocSetContextCreateExtended(MemoryContext parent,
                                                          const char *name,
-                                                         int flags,
                                                          Size minContextSize,
                                                          Size initBlockSize,
                                                          Size maxBlockSize);
 
 /*
- * This backwards compatibility macro only works for constant context names,
- * and you must specify block sizes with one of the abstraction macros below.
+ * This wrapper macro exists to check for non-constant strings used as context
+ * names; that's no longer supported.  (Use MemoryContextSetIdentifier if you
+ * want to provide a variable identifier.)  Note you must specify block sizes
+ * with one of the abstraction macros below.
  */
 #ifdef HAVE__BUILTIN_CONSTANT_P
 #define AllocSetContextCreate(parent, name, allocparams) \
        (StaticAssertExpr(__builtin_constant_p(name), \
-                                         "Use AllocSetContextCreateExtended with MEMCONTEXT_COPY_NAME for non-constant context names"), \
-        AllocSetContextCreateExtended(parent, name, 0, allocparams))
+                                         "memory context names must be constant strings"), \
+        AllocSetContextCreateExtended(parent, name, allocparams))
 #else
 #define AllocSetContextCreate(parent, name, allocparams) \
-       AllocSetContextCreateExtended(parent, name, 0, allocparams)
+       AllocSetContextCreateExtended(parent, name, allocparams)
 #endif
 
 /* slab.c */
 extern MemoryContext SlabContextCreate(MemoryContext parent,
                                  const char *name,
-                                 int flags,
                                  Size blockSize,
                                  Size chunkSize);
 
 /* generation.c */
 extern MemoryContext GenerationContextCreate(MemoryContext parent,
                                                const char *name,
-                                               int flags,
                                                Size blockSize);
 
-/*
- * Flag option bits for FooContextCreate functions.
- * In future, some of these might be relevant to only some context types.
- *
- * COPY_NAME: FooContextCreate's name argument is not a constant string
- */
-#define MEMCONTEXT_COPY_NAME           0x0001  /* is passed name transient? */
-
 /*
  * Recommended default alloc parameters, suitable for "ordinary" contexts
  * that might hold quite a lot of data.
index d44089aedcc845aeb81cf4db2399069ce62d7bc5..7c0d6655498faba0ee0e0bfa25d53ecc7dcb4a93 100644 (file)
@@ -2782,10 +2782,9 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
                /************************************************************
                 * Allocate a context that will hold all PG data for the procedure.
                 ************************************************************/
-               proc_cxt = AllocSetContextCreateExtended(TopMemoryContext,
-                                                                                                NameStr(procStruct->proname),
-                                                                                                MEMCONTEXT_COPY_NAME,
-                                                                                                ALLOCSET_SMALL_SIZES);
+               proc_cxt = AllocSetContextCreate(TopMemoryContext,
+                                                                                "PL/Perl function",
+                                                                                ALLOCSET_SMALL_SIZES);
 
                /************************************************************
                 * Allocate and fill a new procedure description block.
@@ -2794,6 +2793,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
                oldcontext = MemoryContextSwitchTo(proc_cxt);
                prodesc = (plperl_proc_desc *) palloc0(sizeof(plperl_proc_desc));
                prodesc->proname = pstrdup(NameStr(procStruct->proname));
+               MemoryContextSetIdentifier(proc_cxt, prodesc->proname);
                prodesc->fn_cxt = proc_cxt;
                prodesc->fn_refcount = 0;
                prodesc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
index b1a0c1cc4f3d0360375d06ce0591753f06095294..96c1622d66cc461cd7f7ad672a864276e1b270bf 100644 (file)
@@ -342,11 +342,12 @@ do_compile(FunctionCallInfo fcinfo,
         * per-function memory context, so it can be reclaimed easily.
         */
        func_cxt = AllocSetContextCreate(TopMemoryContext,
-                                                                        "PL/pgSQL function context",
+                                                                        "PL/pgSQL function",
                                                                         ALLOCSET_DEFAULT_SIZES);
        plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
 
        function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
+       MemoryContextSetIdentifier(func_cxt, function->fn_signature);
        function->fn_oid = fcinfo->flinfo->fn_oid;
        function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
        function->fn_tid = procTup->t_self;
@@ -2453,7 +2454,7 @@ plpgsql_HashTableInit(void)
        memset(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(PLpgSQL_func_hashkey);
        ctl.entrysize = sizeof(plpgsql_HashEnt);
-       plpgsql_HashTable = hash_create("PLpgSQL function cache",
+       plpgsql_HashTable = hash_create("PLpgSQL function hash",
                                                                        FUNCS_PER_USER,
                                                                        &ctl,
                                                                        HASH_ELEM | HASH_BLOBS);
index b4c4dcdb6c2defac5e09c68d2a6fee1d80db8c3f..16f1278b3729680e870d3cbe92acbf6588224621 100644 (file)
@@ -164,10 +164,9 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
        }
 
        /* Create long-lived context that all procedure info will live in */
-       cxt = AllocSetContextCreateExtended(TopMemoryContext,
-                                                                               procName,
-                                                                               MEMCONTEXT_COPY_NAME,
-                                                                               ALLOCSET_DEFAULT_SIZES);
+       cxt = AllocSetContextCreate(TopMemoryContext,
+                                                               "PL/Python function",
+                                                               ALLOCSET_DEFAULT_SIZES);
 
        oldcxt = MemoryContextSwitchTo(cxt);
 
@@ -183,6 +182,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
                int                     i;
 
                proc->proname = pstrdup(NameStr(procStruct->proname));
+               MemoryContextSetIdentifier(cxt, proc->proname);
                proc->pyname = pstrdup(procName);
                proc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
                proc->fn_tid = procTup->t_self;
index 865071bc3bdc89c10c3f98233b59a6baa1feeb64..558cabc94930cb1855478744c5370cdb5e3c8196 100644 (file)
@@ -1479,12 +1479,10 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
 
                /************************************************************
                 * Allocate a context that will hold all PG data for the procedure.
-                * We use the internal proc name as the context name.
                 ************************************************************/
-               proc_cxt = AllocSetContextCreateExtended(TopMemoryContext,
-                                                                                                internal_proname,
-                                                                                                MEMCONTEXT_COPY_NAME,
-                                                                                                ALLOCSET_SMALL_SIZES);
+               proc_cxt = AllocSetContextCreate(TopMemoryContext,
+                                                                                "PL/Tcl function",
+                                                                                ALLOCSET_SMALL_SIZES);
 
                /************************************************************
                 * Allocate and fill a new procedure description block.
@@ -1493,6 +1491,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
                oldcontext = MemoryContextSwitchTo(proc_cxt);
                prodesc = (pltcl_proc_desc *) palloc0(sizeof(pltcl_proc_desc));
                prodesc->user_proname = pstrdup(NameStr(procStruct->proname));
+               MemoryContextSetIdentifier(proc_cxt, prodesc->user_proname);
                prodesc->internal_proname = pstrdup(internal_proname);
                prodesc->fn_cxt = proc_cxt;
                prodesc->fn_refcount = 0;