1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00

Limit the verbosity of memory context statistics dumps.

We had a report from Stefan Kaltenbrunner of a case in which postmaster
log files overran available disk space because multiple backends spewed
enormous context stats dumps upon hitting an out-of-memory condition.
Given the lack of similar reports, this isn't a common problem, but it
still seems worth doing something about.  However, we don't want to just
blindly truncate the output, because that might prevent diagnosis of OOM
problems.  What seems like a workable compromise is to limit the dump to
100 child contexts per parent, and summarize the space used within any
additional child contexts.  That should help because practical cases where
the dump gets long will typically be huge numbers of siblings under the
same parent context; while the additional debugging value from seeing
details about individual siblings beyond 100 will not be large, we hope.
Anyway it doesn't take much code or memory space to do this, so let's try
it like this and see how things go.

Since the summarization mechanism requires passing totals back up anyway,
I took the opportunity to add a "grand total" line to the end of the
printout.
This commit is contained in:
Tom Lane
2015-08-25 13:09:48 -04:00
parent e39c4afcfa
commit 7b5ef8f2d0
4 changed files with 143 additions and 22 deletions

View File

@@ -253,7 +253,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);
static void AllocSetStats(MemoryContext context, int level, bool print,
MemoryContextCounters *totals);
#ifdef MEMORY_CONTEXT_CHECKING
static void AllocSetCheck(MemoryContext context);
@@ -1228,20 +1229,23 @@ AllocSetIsEmpty(MemoryContext context)
/*
* AllocSetStats
* Displays stats about memory consumption of an allocset.
* 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.
*/
static void
AllocSetStats(MemoryContext context, int level)
AllocSetStats(MemoryContext context, int level, bool print,
MemoryContextCounters *totals)
{
AllocSet set = (AllocSet) context;
Size nblocks = 0;
Size nchunks = 0;
Size freechunks = 0;
Size totalspace = 0;
Size freespace = 0;
AllocBlock block;
AllocChunk chunk;
int fidx;
int i;
for (block = set->blocks; block != NULL; block = block->next)
{
@@ -1251,21 +1255,35 @@ AllocSetStats(MemoryContext context, int level)
}
for (fidx = 0; fidx < ALLOCSET_NUM_FREELISTS; fidx++)
{
AllocChunk chunk;
for (chunk = set->freelist[fidx]; chunk != NULL;
chunk = (AllocChunk) chunk->aset)
{
nchunks++;
freechunks++;
freespace += chunk->size + ALLOC_CHUNKHDRSZ;
}
}
for (i = 0; i < level; i++)
fprintf(stderr, " ");
if (print)
{
int i;
fprintf(stderr,
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, nchunks,
totalspace - freespace);
set->header.name, totalspace, nblocks, freespace, freechunks,
totalspace - freespace);
}
if (totals)
{
totals->nblocks += nblocks;
totals->freechunks += freechunks;
totals->totalspace += totalspace;
totals->freespace += freespace;
}
}