From a249feb0e7654865f53f3853c310a5cec58e185e Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Wed, 20 Aug 2025 10:55:27 +0530 Subject: [PATCH 10/19] 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 8f3e2741051..bc70a3ee6c9 100644 --- a/doc/src/sgml/system-views.sgml +++ b/doc/src/sgml/system-views.sgml @@ -4233,6 +4233,15 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx + + + segment text + + + The name of the shared memory segment concerning the allocation. + + + off int8 diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index c7240250c07..94a2b5a9a67 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -668,6 +668,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(""); - 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(""); + 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 e631323a325..8f1d0b7c031 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -8576,8 +8576,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?', @@ -8600,6 +8600,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 83f566d3218..60c08081b69 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1772,14 +1772,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