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

Reply via email to