0010-WIP-Monitoring-views-20250918.patch
application/x-patch
Filename: 0010-WIP-Monitoring-views-20250918.patch
Type: application/x-patch
Part: 9
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0010
Subject: WIP: Monitoring views
| File | + | − |
|---|---|---|
| doc/src/sgml/system-views.sgml | 9 | 0 |
| src/backend/catalog/system_views.sql | 7 | 0 |
| src/backend/storage/ipc/shmem.c | 72 | 18 |
| src/include/catalog/pg_proc.dat | 10 | 2 |
| src/include/storage/pg_shmem.h | 0 | 1 |
| src/include/storage/shmem.h | 1 | 0 |
| src/test/regress/expected/rules.out | 9 | 1 |
From 86fb36cab8e2079fde361380ae42fe4dbabe7967 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Date: Wed, 20 Aug 2025 10:55:27 +0530
Subject: [PATCH 10/16] WIP: Monitoring views
Modifies pg_shmem_allocations to report shared memory segment as well.
Adds pg_shmem_segments to report shared memory segment information.
TODO:
This commit should be merged with the earlier commit introducing
multiple shared memory segments.
Author: Ashutosh Bapat
---
doc/src/sgml/system-views.sgml | 9 +++
src/backend/catalog/system_views.sql | 7 +++
src/backend/storage/ipc/shmem.c | 90 ++++++++++++++++++++++------
src/include/catalog/pg_proc.dat | 12 +++-
src/include/storage/pg_shmem.h | 1 -
src/include/storage/shmem.h | 1 +
src/test/regress/expected/rules.out | 10 +++-
7 files changed, 108 insertions(+), 22 deletions(-)
diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index 89be9bc333f..7d14a6eca24 100644
--- a/doc/src/sgml/system-views.sgml
+++ b/doc/src/sgml/system-views.sgml
@@ -4167,6 +4167,15 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
</para></entry>
</row>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>segment</structfield> <type>text</type>
+ </para>
+ <para>
+ The name of the shared memory segment concerning the allocation.
+ </para></entry>
+ </row>
+
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>off</structfield> <type>int8</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 46fc28396de..f659dbb2f86 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -658,6 +658,13 @@ GRANT SELECT ON pg_shmem_allocations TO pg_read_all_stats;
REVOKE EXECUTE ON FUNCTION pg_get_shmem_allocations() FROM PUBLIC;
GRANT EXECUTE ON FUNCTION pg_get_shmem_allocations() TO pg_read_all_stats;
+CREATE VIEW pg_shmem_segments AS
+ SELECT * FROM pg_get_shmem_segments();
+
+REVOKE ALL ON pg_shmem_segments FROM PUBLIC;
+GRANT SELECT ON pg_shmem_segments TO pg_read_all_stats;
+REVOKE EXECUTE ON FUNCTION pg_get_shmem_segments() FROM PUBLIC;
+GRANT EXECUTE ON FUNCTION pg_get_shmem_segments() TO pg_read_all_stats;
CREATE VIEW pg_shmem_allocations_numa AS
SELECT * FROM pg_get_shmem_allocations_numa();
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 90c21a97225..9499f332e77 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -531,6 +531,7 @@ ShmemInitStructInSegment(const char *name, Size size, bool *foundPtr,
result->size = size;
result->allocated_size = allocated_size;
result->location = structPtr;
+ result->shmem_segment = shmem_segment;
}
LWLockRelease(ShmemIndexLock);
@@ -582,13 +583,14 @@ mul_size(Size s1, Size s2)
Datum
pg_get_shmem_allocations(PG_FUNCTION_ARGS)
{
-#define PG_GET_SHMEM_SIZES_COLS 4
+#define PG_GET_SHMEM_SIZES_COLS 5
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
HASH_SEQ_STATUS hstat;
ShmemIndexEnt *ent;
- Size named_allocated = 0;
+ Size named_allocated[ANON_MAPPINGS] = {0};
Datum values[PG_GET_SHMEM_SIZES_COLS];
bool nulls[PG_GET_SHMEM_SIZES_COLS];
+ int i;
InitMaterializedSRF(fcinfo, 0);
@@ -598,33 +600,42 @@ pg_get_shmem_allocations(PG_FUNCTION_ARGS)
/* output all allocated entries */
memset(nulls, 0, sizeof(nulls));
- /* XXX: take all shared memory segments into account. */
while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL)
{
values[0] = CStringGetTextDatum(ent->key);
- values[1] = Int64GetDatum((char *) ent->location - (char *) Segments[MAIN_SHMEM_SEGMENT].ShmemSegHdr);
- values[2] = Int64GetDatum(ent->size);
- values[3] = Int64GetDatum(ent->allocated_size);
- named_allocated += ent->allocated_size;
+ values[1] = CStringGetTextDatum(MappingName(ent->shmem_segment));
+ values[2] = Int64GetDatum((char *) ent->location - (char *) Segments[ent->shmem_segment].ShmemSegHdr);
+ values[3] = Int64GetDatum(ent->size);
+ values[4] = Int64GetDatum(ent->allocated_size);
+ named_allocated[ent->shmem_segment] += ent->allocated_size;
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
}
/* output shared memory allocated but not counted via the shmem index */
- values[0] = CStringGetTextDatum("<anonymous>");
- nulls[1] = true;
- values[2] = Int64GetDatum(Segments[MAIN_SHMEM_SEGMENT].ShmemSegHdr->freeoffset - named_allocated);
- values[3] = values[2];
- tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+ for (i = 0; i < ANON_MAPPINGS; i++)
+ {
+ values[0] = CStringGetTextDatum("<anonymous>");
+ values[1] = CStringGetTextDatum(MappingName(i));
+ nulls[2] = true;
+ values[3] = Int64GetDatum(Segments[i].ShmemSegHdr->freeoffset - named_allocated[i]);
+ values[4] = values[3];
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+ }
/* output as-of-yet unused shared memory */
- nulls[0] = true;
- values[1] = Int64GetDatum(Segments[MAIN_SHMEM_SEGMENT].ShmemSegHdr->freeoffset);
- nulls[1] = false;
- values[2] = Int64GetDatum(Segments[MAIN_SHMEM_SEGMENT].ShmemSegHdr->totalsize - Segments[MAIN_SHMEM_SEGMENT].ShmemSegHdr->freeoffset);
- values[3] = values[2];
- tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+ memset(nulls, 0, sizeof(nulls));
+
+ for (i = 0; i < ANON_MAPPINGS; i++)
+ {
+ nulls[0] = true;
+ values[1] = CStringGetTextDatum(MappingName(i));
+ values[2] = Int64GetDatum(Segments[i].ShmemSegHdr->freeoffset);
+ values[3] = Int64GetDatum(Segments[i].ShmemSegHdr->totalsize - Segments[i].ShmemSegHdr->freeoffset);
+ values[4] = values[3];
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+ }
LWLockRelease(ShmemIndexLock);
@@ -825,3 +836,46 @@ pg_numa_available(PG_FUNCTION_ARGS)
{
PG_RETURN_BOOL(pg_numa_init() != -1);
}
+
+/* SQL SRF showing shared memory segments */
+Datum
+pg_get_shmem_segments(PG_FUNCTION_ARGS)
+{
+#define PG_GET_SHMEM_SEGS_COLS 6
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ Datum values[PG_GET_SHMEM_SEGS_COLS];
+ bool nulls[PG_GET_SHMEM_SEGS_COLS];
+ int i;
+
+ InitMaterializedSRF(fcinfo, 0);
+
+ /* output all allocated entries */
+ for (i = 0; i < ANON_MAPPINGS; i++)
+ {
+ PGShmemHeader *shmhdr = Segments[i].ShmemSegHdr;
+ AnonymousMapping *segmapping = &Mappings[i];
+ int j;
+
+ if (shmhdr == NULL)
+ {
+ for (j = 0; j < PG_GET_SHMEM_SEGS_COLS; j++)
+ nulls[j] = true;
+ }
+ else
+ {
+ memset(nulls, 0, sizeof(nulls));
+ values[0] = Int32GetDatum(i);
+ values[1] = CStringGetTextDatum(MappingName(i));
+ values[2] = Int64GetDatum(shmhdr->totalsize);
+ values[3] = Int64GetDatum(shmhdr->freeoffset);
+ values[4] = Int64GetDatum(segmapping->shmem_size);
+ values[5] = Int64GetDatum(segmapping->shmem_reserved);
+ }
+
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
+ }
+
+ return (Datum) 0;
+}
+
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1e53b7a4ae5..6c37fa90c89 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8568,8 +8568,8 @@
{ oid => '5052', descr => 'allocations from the main shared memory segment',
proname => 'pg_get_shmem_allocations', prorows => '50', proretset => 't',
provolatile => 'v', prorettype => 'record', proargtypes => '',
- proallargtypes => '{text,int8,int8,int8}', proargmodes => '{o,o,o,o}',
- proargnames => '{name,off,size,allocated_size}',
+ proallargtypes => '{text,text,int8,int8,int8}', proargmodes => '{o,o,o,o,o}',
+ proargnames => '{name,segment,off,size,allocated_size}',
prosrc => 'pg_get_shmem_allocations' },
{ oid => '4099', descr => 'Is NUMA support available?',
@@ -8592,6 +8592,14 @@
proargmodes => '{o,o,o}', proargnames => '{name,type,size}',
prosrc => 'pg_get_dsm_registry_allocations' },
+# shared memory segments
+{ oid => '5101', descr => 'shared memory segments',
+ proname => 'pg_get_shmem_segments', prorows => '6', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{int4,text,int8,int8,int8,int8}', proargmodes => '{o,o,o,o,o,o}',
+ proargnames => '{id,name,size,freeoffset,mapping_size,mapping_reserved_size}',
+ prosrc => 'pg_get_shmem_segments' },
+
# buffer lookup table
{ oid => '5102',
descr => 'shared buffer lookup table',
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
index a1fa6b43fe3..715f6acb5dd 100644
--- a/src/include/storage/pg_shmem.h
+++ b/src/include/storage/pg_shmem.h
@@ -69,7 +69,6 @@ typedef struct ShmemSegment
extern PGDLLIMPORT ShmemSegment Segments[ANON_MAPPINGS];
extern PGDLLIMPORT AnonymousMapping Mappings[ANON_MAPPINGS];
-
/* GUC variables */
extern PGDLLIMPORT int shared_memory_type;
extern PGDLLIMPORT int huge_pages;
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index 910c43f54f4..64ff5a286ba 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -71,6 +71,7 @@ typedef struct
void *location; /* location in shared mem */
Size size; /* # bytes requested for the structure */
Size allocated_size; /* # bytes actually allocated */
+ int shmem_segment; /* segment in which the structure is allocated */
} ShmemIndexEnt;
#endif /* SHMEM_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 760bb13fe95..e73314b5ef0 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1764,14 +1764,22 @@ pg_shadow| SELECT pg_authid.rolname AS usename,
LEFT JOIN pg_db_role_setting s ON (((pg_authid.oid = s.setrole) AND (s.setdatabase = (0)::oid))))
WHERE pg_authid.rolcanlogin;
pg_shmem_allocations| SELECT name,
+ segment,
off,
size,
allocated_size
- FROM pg_get_shmem_allocations() pg_get_shmem_allocations(name, off, size, allocated_size);
+ FROM pg_get_shmem_allocations() pg_get_shmem_allocations(name, segment, off, size, allocated_size);
pg_shmem_allocations_numa| SELECT name,
numa_node,
size
FROM pg_get_shmem_allocations_numa() pg_get_shmem_allocations_numa(name, numa_node, size);
+pg_shmem_segments| SELECT id,
+ name,
+ size,
+ freeoffset,
+ mapping_size,
+ mapping_reserved_size
+ FROM pg_get_shmem_segments() pg_get_shmem_segments(id, name, size, freeoffset, mapping_size, mapping_reserved_size);
pg_stat_activity| SELECT s.datid,
d.datname,
s.pid,
--
2.34.1