Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3e98c0b

Browse files
committed
Add pg_backend_memory_contexts system view.
This view displays the usages of all the memory contexts of the server process attached to the current session. This information is useful to investigate the cause of backend-local memory bloat. This information can be also collected by calling MemoryContextStats(TopMemoryContext) via a debugger. But this technique cannot be uesd in some environments because no debugger is available there. And it outputs lots of text messages and it's not easy to analyze them. So, pg_backend_memory_contexts view allows us to access to backend-local memory contexts information more easily. Bump catalog version. Author: Atsushi Torikoshi, Fujii Masao Reviewed-by: Tatsuhito Kasahara, Andres Freund, Daniel Gustafsson, Robert Haas, Michael Paquier Discussion: https://postgr.es/m/72a656e0f71d0860161e0b3f67e4d771@oss.nttdata.com
1 parent 07f32fc commit 3e98c0b

File tree

6 files changed

+283
-1
lines changed

6 files changed

+283
-1
lines changed

doc/src/sgml/catalogs.sgml

+122
Original file line numberDiff line numberDiff line change
@@ -9226,6 +9226,11 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
92269226
<entry>available versions of extensions</entry>
92279227
</row>
92289228

9229+
<row>
9230+
<entry><link linkend="view-pg-backend-memory-contexts"><structname>pg_backend_memory_contexts</structname></link></entry>
9231+
<entry>backend memory contexts</entry>
9232+
</row>
9233+
92299234
<row>
92309235
<entry><link linkend="view-pg-config"><structname>pg_config</structname></link></entry>
92319236
<entry>compile-time configuration parameters</entry>
@@ -9577,6 +9582,123 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
95779582
</para>
95789583
</sect1>
95799584

9585+
<sect1 id="view-pg-backend-memory-contexts">
9586+
<title><structname>pg_backend_memory_contexts</structname></title>
9587+
9588+
<indexterm zone="view-pg-backend-memory-contexts">
9589+
<primary>pg_backend_memory_contexts</primary>
9590+
</indexterm>
9591+
9592+
<para>
9593+
The view <structname>pg_backend_memory_contexts</structname> displays all
9594+
the memory contexts of the server process attached to the current session.
9595+
</para>
9596+
<para>
9597+
<structname>pg_backend_memory_contexts</structname> contains one row
9598+
for each memory context.
9599+
</para>
9600+
9601+
<table>
9602+
<title><structname>pg_backend_memory_contexts</structname> Columns</title>
9603+
<tgroup cols="1">
9604+
<thead>
9605+
<row>
9606+
<entry role="catalog_table_entry"><para role="column_definition">
9607+
Column Type
9608+
</para>
9609+
<para>
9610+
Description
9611+
</para></entry>
9612+
</row>
9613+
</thead>
9614+
9615+
<tbody>
9616+
<row>
9617+
<entry role="catalog_table_entry"><para role="column_definition">
9618+
<structfield>name</structfield> <type>text</type>
9619+
</para>
9620+
<para>
9621+
Name of the memory context
9622+
</para></entry>
9623+
</row>
9624+
9625+
<row>
9626+
<entry role="catalog_table_entry"><para role="column_definition">
9627+
<structfield>ident</structfield> <type>text</type>
9628+
</para>
9629+
<para>
9630+
Identification information of the memory context. This field is truncated at 1024 bytes
9631+
</para></entry>
9632+
</row>
9633+
9634+
<row>
9635+
<entry role="catalog_table_entry"><para role="column_definition">
9636+
<structfield>parent</structfield> <type>text</type>
9637+
</para>
9638+
<para>
9639+
Name of the parent of this memory context
9640+
</para></entry>
9641+
</row>
9642+
9643+
<row>
9644+
<entry role="catalog_table_entry"><para role="column_definition">
9645+
<structfield>level</structfield> <type>int4</type>
9646+
</para>
9647+
<para>
9648+
Distance from TopMemoryContext in context tree
9649+
</para></entry>
9650+
</row>
9651+
9652+
<row>
9653+
<entry role="catalog_table_entry"><para role="column_definition">
9654+
<structfield>total_bytes</structfield> <type>int8</type>
9655+
</para>
9656+
<para>
9657+
Total bytes allocated for this memory context
9658+
</para></entry>
9659+
</row>
9660+
9661+
<row>
9662+
<entry role="catalog_table_entry"><para role="column_definition">
9663+
<structfield>total_nblocks</structfield> <type>int8</type>
9664+
</para>
9665+
<para>
9666+
Total number of blocks allocated for this memory context
9667+
</para></entry>
9668+
</row>
9669+
9670+
<row>
9671+
<entry role="catalog_table_entry"><para role="column_definition">
9672+
<structfield>free_bytes</structfield> <type>int8</type>
9673+
</para>
9674+
<para>
9675+
Free space in bytes
9676+
</para></entry>
9677+
</row>
9678+
9679+
<row>
9680+
<entry role="catalog_table_entry"><para role="column_definition">
9681+
<structfield>free_chunks</structfield> <type>int8</type>
9682+
</para>
9683+
<para>
9684+
Total number of free chunks
9685+
</para></entry>
9686+
</row>
9687+
9688+
<row>
9689+
<entry role="catalog_table_entry"><para role="column_definition">
9690+
<structfield>used_bytes</structfield> <type>int8</type>
9691+
</para>
9692+
<para>
9693+
Used space in bytes
9694+
</para></entry>
9695+
</row>
9696+
</tbody>
9697+
</tgroup>
9698+
</table>
9699+
9700+
</sect1>
9701+
95809702
<sect1 id="view-pg-config">
95819703
<title><structname>pg_config</structname></title>
95829704

src/backend/catalog/system_views.sql

+3
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,9 @@ CREATE VIEW pg_shmem_allocations AS
554554
REVOKE ALL ON pg_shmem_allocations FROM PUBLIC;
555555
REVOKE EXECUTE ON FUNCTION pg_get_shmem_allocations() FROM PUBLIC;
556556

557+
CREATE VIEW pg_backend_memory_contexts AS
558+
SELECT * FROM pg_get_backend_memory_contexts();
559+
557560
-- Statistics views
558561

559562
CREATE VIEW pg_stat_all_tables AS

src/backend/utils/mmgr/mcxt.c

+138
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121

2222
#include "postgres.h"
2323

24+
#include "funcapi.h"
2425
#include "mb/pg_wchar.h"
2526
#include "miscadmin.h"
27+
#include "utils/builtins.h"
2628
#include "utils/memdebug.h"
2729
#include "utils/memutils.h"
2830

@@ -67,6 +69,12 @@ static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
6769
#define AssertNotInCriticalSection(context) \
6870
Assert(CritSectionCount == 0 || (context)->allowInCritSection)
6971

72+
/* ----------
73+
* The max bytes for showing identifiers of MemoryContext.
74+
* ----------
75+
*/
76+
#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE 1024
77+
7078
/*****************************************************************************
7179
* EXPORTED ROUTINES *
7280
*****************************************************************************/
@@ -1220,3 +1228,133 @@ pchomp(const char *in)
12201228
n--;
12211229
return pnstrdup(in, n);
12221230
}
1231+
1232+
/*
1233+
* PutMemoryContextsStatsTupleStore
1234+
* One recursion level for pg_get_backend_memory_contexts.
1235+
*/
1236+
static void
1237+
PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore,
1238+
TupleDesc tupdesc, MemoryContext context,
1239+
const char *parent, int level)
1240+
{
1241+
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS 9
1242+
1243+
Datum values[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS];
1244+
bool nulls[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS];
1245+
MemoryContextCounters stat;
1246+
MemoryContext child;
1247+
const char *name;
1248+
const char *ident;
1249+
1250+
AssertArg(MemoryContextIsValid(context));
1251+
1252+
name = context->name;
1253+
ident = context->ident;
1254+
1255+
/*
1256+
* To be consistent with logging output, we label dynahash contexts
1257+
* with just the hash table name as with MemoryContextStatsPrint().
1258+
*/
1259+
if (ident && strcmp(name, "dynahash") == 0)
1260+
{
1261+
name = ident;
1262+
ident = NULL;
1263+
}
1264+
1265+
/* Examine the context itself */
1266+
memset(&stat, 0, sizeof(stat));
1267+
(*context->methods->stats) (context, NULL, (void *) &level, &stat);
1268+
1269+
memset(values, 0, sizeof(values));
1270+
memset(nulls, 0, sizeof(nulls));
1271+
1272+
if (name)
1273+
values[0] = CStringGetTextDatum(name);
1274+
else
1275+
nulls[0] = true;
1276+
1277+
if (ident)
1278+
{
1279+
int idlen = strlen(ident);
1280+
char clipped_ident[MEMORY_CONTEXT_IDENT_DISPLAY_SIZE];
1281+
1282+
/*
1283+
* Some identifiers such as SQL query string can be very long,
1284+
* truncate oversize identifiers.
1285+
*/
1286+
if (idlen >= MEMORY_CONTEXT_IDENT_DISPLAY_SIZE)
1287+
idlen = pg_mbcliplen(ident, idlen, MEMORY_CONTEXT_IDENT_DISPLAY_SIZE - 1);
1288+
1289+
memcpy(clipped_ident, ident, idlen);
1290+
clipped_ident[idlen] = '\0';
1291+
values[1] = CStringGetTextDatum(clipped_ident);
1292+
}
1293+
else
1294+
nulls[1] = true;
1295+
1296+
if (parent)
1297+
values[2] = CStringGetTextDatum(parent);
1298+
else
1299+
nulls[2] = true;
1300+
1301+
values[3] = Int32GetDatum(level);
1302+
values[4] = Int64GetDatum(stat.totalspace);
1303+
values[5] = Int64GetDatum(stat.nblocks);
1304+
values[6] = Int64GetDatum(stat.freespace);
1305+
values[7] = Int64GetDatum(stat.freechunks);
1306+
values[8] = Int64GetDatum(stat.totalspace - stat.freespace);
1307+
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
1308+
1309+
for (child = context->firstchild; child != NULL; child = child->nextchild)
1310+
{
1311+
PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
1312+
child, name, level + 1);
1313+
}
1314+
}
1315+
1316+
/*
1317+
* pg_get_backend_memory_contexts
1318+
* SQL SRF showing backend memory context.
1319+
*/
1320+
Datum
1321+
pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
1322+
{
1323+
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1324+
TupleDesc tupdesc;
1325+
Tuplestorestate *tupstore;
1326+
MemoryContext per_query_ctx;
1327+
MemoryContext oldcontext;
1328+
1329+
/* check to see if caller supports us returning a tuplestore */
1330+
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
1331+
ereport(ERROR,
1332+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1333+
errmsg("set-valued function called in context that cannot accept a set")));
1334+
if (!(rsinfo->allowedModes & SFRM_Materialize))
1335+
ereport(ERROR,
1336+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1337+
errmsg("materialize mode required, but it is not allowed in this context")));
1338+
1339+
/* Build a tuple descriptor for our result type */
1340+
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1341+
elog(ERROR, "return type must be a row type");
1342+
1343+
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
1344+
oldcontext = MemoryContextSwitchTo(per_query_ctx);
1345+
1346+
tupstore = tuplestore_begin_heap(true, false, work_mem);
1347+
rsinfo->returnMode = SFRM_Materialize;
1348+
rsinfo->setResult = tupstore;
1349+
rsinfo->setDesc = tupdesc;
1350+
1351+
MemoryContextSwitchTo(oldcontext);
1352+
1353+
PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
1354+
TopMemoryContext, NULL, 0);
1355+
1356+
/* clean up and return the tuplestore */
1357+
tuplestore_donestoring(tupstore);
1358+
1359+
return (Datum) 0;
1360+
}

src/include/catalog/catversion.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 202007251
56+
#define CATALOG_VERSION_NO 202008191
5757

5858
#endif

src/include/catalog/pg_proc.dat

+9
Original file line numberDiff line numberDiff line change
@@ -7807,6 +7807,15 @@
78077807
proargnames => '{name,off,size,allocated_size}',
78087808
prosrc => 'pg_get_shmem_allocations' },
78097809

7810+
# memory context of local backend
7811+
{ oid => '2282', descr => 'information about all memory contexts of local backend',
7812+
proname => 'pg_get_backend_memory_contexts', prorows => '100', proretset => 't',
7813+
provolatile => 'v', proparallel => 'r', prorettype => 'record', proargtypes => '',
7814+
proallargtypes => '{text,text,text,int4,int8,int8,int8,int8,int8}',
7815+
proargmodes => '{o,o,o,o,o,o,o,o,o}',
7816+
proargnames => '{name, ident, parent, level, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes}',
7817+
prosrc => 'pg_get_backend_memory_contexts' },
7818+
78107819
# non-persistent series generator
78117820
{ oid => '1066', descr => 'non-persistent series generator',
78127821
proname => 'generate_series', prorows => '1000',

src/test/regress/expected/rules.out

+10
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,16 @@ pg_available_extensions| SELECT e.name,
13241324
e.comment
13251325
FROM (pg_available_extensions() e(name, default_version, comment)
13261326
LEFT JOIN pg_extension x ON ((e.name = x.extname)));
1327+
pg_backend_memory_contexts| SELECT pg_get_backend_memory_contexts.name,
1328+
pg_get_backend_memory_contexts.ident,
1329+
pg_get_backend_memory_contexts.parent,
1330+
pg_get_backend_memory_contexts.level,
1331+
pg_get_backend_memory_contexts.total_bytes,
1332+
pg_get_backend_memory_contexts.total_nblocks,
1333+
pg_get_backend_memory_contexts.free_bytes,
1334+
pg_get_backend_memory_contexts.free_chunks,
1335+
pg_get_backend_memory_contexts.used_bytes
1336+
FROM pg_get_backend_memory_contexts() pg_get_backend_memory_contexts(name, ident, parent, level, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes);
13271337
pg_config| SELECT pg_config.name,
13281338
pg_config.setting
13291339
FROM pg_config() pg_config(name, setting);

0 commit comments

Comments
 (0)