Previously, MemoryContextStats() simply emitted a line of output for
each MemoryContext. This is fine, but it makes it difficult to see the
shape of the MemoryContext hierarchy. Attached is a trivial patch to
indent each context by "4 * level" spaces, where "level" is the depth of
the node within the subtree printed by MemoryContextStats().
For example, suppose we have three contexts beneath TopMemoryContext:
TopMemoryContext (...)
FooContext (...)
BarContext (...)
BazContext (...)
With the patch, these might be printed as:
TopMemoryContext (...)
FooContext (...)
BarContext (...)
BazContext (...)
Assuming that's the parent/child relationship between them, of course.
Obviously this is just for debugging, but I've found it useful while
looking at some memory-related issues. Any comments or objections to
including this in HEAD?
-Neil
Index: source/src/backend/utils/mmgr/aset.c
===================================================================
RCS file: /home/neilc/postgres/cvs_root/pgsql/src/backend/utils/mmgr/aset.c,v
retrieving revision 1.72
diff -p -c -r1.72 aset.c
*** source/src/backend/utils/mmgr/aset.c 30 Apr 2007 00:12:08 -0000 1.72
--- source/src/backend/utils/mmgr/aset.c 7 Aug 2007 00:29:41 -0000
*************** static void AllocSetReset(MemoryContext
*** 214,220 ****
static void AllocSetDelete(MemoryContext context);
static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer);
static bool AllocSetIsEmpty(MemoryContext context);
! static void AllocSetStats(MemoryContext context);
#ifdef MEMORY_CONTEXT_CHECKING
static void AllocSetCheck(MemoryContext context);
--- 214,220 ----
static void AllocSetDelete(MemoryContext context);
static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer);
static bool AllocSetIsEmpty(MemoryContext context);
! static void AllocSetStats(MemoryContext context, int level);
#ifdef MEMORY_CONTEXT_CHECKING
static void AllocSetCheck(MemoryContext context);
*************** AllocSetIsEmpty(MemoryContext context)
*** 1034,1040 ****
* Displays stats about memory consumption of an allocset.
*/
static void
! AllocSetStats(MemoryContext context)
{
AllocSet set = (AllocSet) context;
long nblocks = 0;
--- 1034,1040 ----
* Displays stats about memory consumption of an allocset.
*/
static void
! AllocSetStats(MemoryContext context, int level)
{
AllocSet set = (AllocSet) context;
long nblocks = 0;
*************** AllocSetStats(MemoryContext context)
*** 1044,1049 ****
--- 1044,1050 ----
AllocBlock block;
AllocChunk chunk;
int fidx;
+ int i;
for (block = set->blocks; block != NULL; block = block->next)
{
*************** AllocSetStats(MemoryContext context)
*** 1060,1065 ****
--- 1061,1070 ----
freespace += chunk->size + ALLOC_CHUNKHDRSZ;
}
}
+
+ for (i = 0; i < level; i++)
+ fprintf(stderr, " ");
+
fprintf(stderr,
"%s: %lu total in %ld blocks; %lu free (%ld chunks); %lu used\n",
set->header.name, totalspace, nblocks, freespace, nchunks,
Index: source/src/backend/utils/mmgr/mcxt.c
===================================================================
RCS file: /home/neilc/postgres/cvs_root/pgsql/src/backend/utils/mmgr/mcxt.c,v
retrieving revision 1.61
diff -p -c -r1.61 mcxt.c
*** source/src/backend/utils/mmgr/mcxt.c 25 Jul 2007 12:22:52 -0000 1.61
--- source/src/backend/utils/mmgr/mcxt.c 7 Aug 2007 00:30:26 -0000
*************** MemoryContext CurTransactionContext = NU
*** 49,54 ****
--- 49,56 ----
/* This is a transient link to the active portal's memory context: */
MemoryContext PortalContext = NULL;
+ static void MemoryContextStatsInternal(MemoryContext context, int level);
+
/*****************************************************************************
* EXPORTED ROUTINES *
*************** MemoryContextIsEmpty(MemoryContext conte
*** 321,336 ****
void
MemoryContextStats(MemoryContext context)
{
MemoryContext child;
AssertArg(MemoryContextIsValid(context));
! (*context->methods->stats) (context);
for (child = context->firstchild; child != NULL; child = child->nextchild)
! MemoryContextStats(child);
}
-
/*
* MemoryContextCheck
* Check all chunks in the named context.
--- 323,343 ----
void
MemoryContextStats(MemoryContext context)
{
+ MemoryContextStatsInternal(context, 0);
+ }
+
+ static void
+ MemoryContextStatsInternal(MemoryContext context, int level)
+ {
MemoryContext child;
AssertArg(MemoryContextIsValid(context));
! (*context->methods->stats) (context, level);
for (child = context->firstchild; child != NULL; child = child->nextchild)
! MemoryContextStatsInternal(child, level + 1);
}
/*
* MemoryContextCheck
* Check all chunks in the named context.
Index: source/src/include/nodes/memnodes.h
===================================================================
RCS file: /home/neilc/postgres/cvs_root/pgsql/src/include/nodes/memnodes.h,v
retrieving revision 1.32
diff -p -c -r1.32 memnodes.h
*** source/src/include/nodes/memnodes.h 5 Jan 2007 22:19:55 -0000 1.32
--- source/src/include/nodes/memnodes.h 7 Aug 2007 00:29:41 -0000
*************** typedef struct MemoryContextMethods
*** 44,50 ****
void (*delete) (MemoryContext context);
Size (*get_chunk_space) (MemoryContext context, void *pointer);
bool (*is_empty) (MemoryContext context);
! void (*stats) (MemoryContext context);
#ifdef MEMORY_CONTEXT_CHECKING
void (*check) (MemoryContext context);
#endif
--- 44,50 ----
void (*delete) (MemoryContext context);
Size (*get_chunk_space) (MemoryContext context, void *pointer);
bool (*is_empty) (MemoryContext context);
! void (*stats) (MemoryContext context, int level);
#ifdef MEMORY_CONTEXT_CHECKING
void (*check) (MemoryContext context);
#endif
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?
http://www.postgresql.org/docs/faq