Re: Creating a function for exposing memory usage of backend process

Andres Freund <andres@anarazel.de>

From: Andres Freund <andres@anarazel.de>
To: torikoshia <torikoshia@oss.nttdata.com>
Cc: Fujii Masao <masao.fujii@oss.nttdata.com>, pgsql-hackers@postgresql.org
Date: 2020-07-08T17:03:48Z
Lists: pgsql-hackers
Hi,

I think this is an incredibly useful feature.


On 2020-07-07 22:02:10 +0900, torikoshia wrote:
> > There can be multiple memory contexts with the same name. So I'm afraid
> > that it's difficult to identify the actual parent memory context from
> > this
> > "parent" column. This is ok when logging memory contexts by calling
> > MemoryContextStats() via gdb. Because child memory contexts are printed
> > just under their parent, with indents. But this doesn't work in the
> > view.
> > To identify the actual parent memory or calculate the memory contexts
> > tree
> > from the view, we might need to assign unique ID to each memory context
> > and display it. But IMO this is overkill. So I'm fine with current
> > "parent"
> > column. Thought? Do you have any better idea?
> 
> Indeed.
> I also feel it's not usual to assign a unique ID, which
> can vary every time the view displayed.

Hm. I wonder if we just could include the address of the context
itself. There might be reasons not to do so (e.g. security concerns
about leaked pointers making attacks easier), but I think it's worth
considering.


> We show each context using a recursive function and this is
> a kind of depth-first search. So, as far as I understand,
> we can identify its parent using both the "parent" column
> and the order of the rows.
> 
> Documenting these things may worth for who want to identify
> the relation between parents and children.
> 
> Of course, in the relational model, the order of relation
> does not have meaning so it's also unusual in this sense..

It makes it pretty hard to write summarizing queries, so I am not a huge
fan of just relying on the order.


> +/*
> + * PutMemoryContextsStatsTupleStore
> + *		One recursion level for pg_get_backend_memory_contexts.
> + */
> +static void
> +PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore,
> +								TupleDesc tupdesc, MemoryContext context,
> +								MemoryContext parent, int level)
> +{
> +#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS	9
> +	Datum		values[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS];
> +	bool		nulls[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS];
> +	MemoryContextCounters stat;
> +	MemoryContext child;
> +	const char *name = context->name;
> +	const char *ident = context->ident;
> +
> +	if (context == NULL)
> +		return;
> +
> +	/*
> +	 * To be consistent with logging output, we label dynahash contexts
> +	 * with just the hash table name as with MemoryContextStatsPrint().
> +	 */
> +	if (ident && strcmp(name, "dynahash") == 0)
> +	{
> +		name = ident;
> +		ident = NULL;
> +	}
> +
> +	/* Examine the context itself */
> +	memset(&stat, 0, sizeof(stat));
> +	(*context->methods->stats) (context, NULL, (void *) &level, &stat);
> +
> +	memset(values, 0, sizeof(values));
> +	memset(nulls, 0, sizeof(nulls));
> +
> +	values[0] = CStringGetTextDatum(name);
> +
> +	if (ident)
> +	{
> +		int		idlen = strlen(ident);
> +		char		clipped_ident[MEMORY_CONTEXT_IDENT_DISPLAY_SIZE];
> +
> +		/*
> +		 * Some identifiers such as SQL query string can be very long,
> +		 * truncate oversize identifiers.
> +		 */
> +		if (idlen >= MEMORY_CONTEXT_IDENT_DISPLAY_SIZE)
> +			idlen = pg_mbcliplen(ident, idlen, MEMORY_CONTEXT_IDENT_DISPLAY_SIZE - 1);
> +

Why?

Greetings,

Andres Freund



Commits

  1. Add regression test for pg_backend_memory_contexts.

  2. Move codes for pg_backend_memory_contexts from mmgr/mcxt.c to adt/mcxtfuncs.c.

  3. Prevent non-superusers from reading pg_backend_memory_contexts, by default.

  4. Add pg_backend_memory_contexts system view.

  5. Fix yet another issue with step generation in partition pruning.