On Thu, Nov 27, 2025 at 01:51:39PM +0530, Rahila Syed wrote: > Thank you for this improvement. I think it will be very helpful to have > the ability to report dsa and dshash memory sizes.
Thanks for reviewing! > 1. As a result of this change, the following comment in > pg_get_dsm_registry_allocations is incorrect. Fixed. > + LWLockAcquire(&control->lock, LW_SHARED); > > The dsa_get_total_size function takes LW_EXCLUSIVE lock for the same > purpose. I wonder why that is the case and whether both should be > consistent. That function was added by commit ee1b30f, which AFAICT used an exclusive lock just to stay consistent with the rest of dsa.c [0]. I don't see any discussion about this in the original DSA thread [1]. Perhaps we could go through dsa.c and switch to LW_SHARED where appropriate, although I doubt it makes much difference. > +size_t > +dsa_get_total_size_from_handle(dsa_handle handle) > > I believe this function will report the size as long as the dsa control > structure is created within a dsm segment, since all dsm segments are > tracked by the global list - dsm_segment_list, regardless of whether the > dsa is created with dsa_create or dsa_create_in_place. In that case, > perhaps we should update the comment above to reflect this. Sorry, I'm not following what you think we should update the comment to say. > 4. Since, with this change, the size column will show memory allocation > regardless of whether it is currently mapped in the local process, I > think it would be helpful to add a boolean column to display the mapped > status as a future enhancement. Maybe, although I'm struggling to think of a scenario where that information would be useful. [0] https://postgr.es/m/CAD21AoDoWrbNf%2BK2Fwg2n%3DCZDHigjkndwqy_86BGgXBp9Kbq4Q%40mail.gmail.com [1] https://postgr.es/m/CAEepm%3D1z5WLuNoJ80PaCvz6EtG9dN0j-KuHcHtU6QEfcPP5-qA%40mail.gmail.com -- nathan
>From df18d34c52f0f744995c4f01b3b05205ed01b535 Mon Sep 17 00:00:00 2001 From: Nathan Bossart <[email protected]> Date: Wed, 26 Nov 2025 16:48:13 -0600 Subject: [PATCH v2 1/1] rework DSM registry view --- doc/src/sgml/system-views.sgml | 4 +-- src/backend/storage/ipc/dsm_registry.c | 22 ++++-------- src/backend/utils/mmgr/dsa.c | 35 +++++++++++++++++++ src/include/utils/dsa.h | 1 + .../expected/test_dsm_registry.out | 4 +-- .../sql/test_dsm_registry.sql | 4 +-- 6 files changed, 49 insertions(+), 21 deletions(-) diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml index 7db8f73eba2..162c76b729a 100644 --- a/doc/src/sgml/system-views.sgml +++ b/doc/src/sgml/system-views.sgml @@ -1150,8 +1150,8 @@ AND c1.path[c2.level] = c2.path[c2.level]; <structfield>size</structfield> <type>int8</type> </para> <para> - Size of the allocation in bytes. NULL for entries of type - <literal>area</literal> and <literal>hash</literal>. + Size of the allocation in bytes. NULL for entries that failed + initialization. </para></entry> </row> </tbody> diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c index ef6533b1100..0f3e08c44d8 100644 --- a/src/backend/storage/ipc/dsm_registry.c +++ b/src/backend/storage/ipc/dsm_registry.c @@ -463,26 +463,18 @@ pg_get_dsm_registry_allocations(PG_FUNCTION_ARGS) Datum vals[3]; bool nulls[3] = {0}; - /* Do not show partially-initialized entries. */ - if (entry->type == DSMR_ENTRY_TYPE_DSM && - entry->dsm.handle == DSM_HANDLE_INVALID) - continue; - if (entry->type == DSMR_ENTRY_TYPE_DSA && - entry->dsa.handle == DSA_HANDLE_INVALID) - continue; - if (entry->type == DSMR_ENTRY_TYPE_DSH && - entry->dsh.dsa_handle == DSA_HANDLE_INVALID) - continue; - vals[0] = CStringGetTextDatum(entry->name); vals[1] = CStringGetTextDatum(DSMREntryTypeNames[entry->type]); - /* - * Since we can't know the size of DSA/dshash entries without first - * attaching to them, return NULL for those. - */ + /* Be careful to only return the sizes of initialized entries. */ if (entry->type == DSMR_ENTRY_TYPE_DSM) vals[2] = Int64GetDatum(entry->dsm.size); + else if (entry->type == DSMR_ENTRY_TYPE_DSA && + entry->dsa.handle != DSA_HANDLE_INVALID) + vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsa.handle)); + else if (entry->type == DSMR_ENTRY_TYPE_DSH && + entry->dsh.dsa_handle !=DSA_HANDLE_INVALID) + vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsh.dsa_handle)); else nulls[2] = true; diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c index be43e9351c3..030f9463712 100644 --- a/src/backend/utils/mmgr/dsa.c +++ b/src/backend/utils/mmgr/dsa.c @@ -1050,6 +1050,41 @@ dsa_get_total_size(dsa_area *area) return size; } +/* + * Same as dsa_get_total_size(), but accepts a DSA handle. The area must have + * been created with dsa_create (not dsa_create_in_place). + */ +size_t +dsa_get_total_size_from_handle(dsa_handle handle) +{ + size_t size; + bool already_attached; + dsm_segment *segment; + dsa_area_control *control; + + already_attached = dsa_is_attached(handle); + if (already_attached) + segment = dsm_find_mapping(handle); + else + segment = dsm_attach(handle); + + if (segment == NULL) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("could not attach to dynamic shared area"))); + + control = (dsa_area_control *) dsm_segment_address(segment); + + LWLockAcquire(&control->lock, LW_SHARED); + size = control->total_segment_size; + LWLockRelease(&control->lock); + + if (!already_attached) + dsm_detach(segment); + + return size; +} + /* * Aggressively free all spare memory in the hope of returning DSM segments to * the operating system. diff --git a/src/include/utils/dsa.h b/src/include/utils/dsa.h index f2104dacbfc..42449ff22de 100644 --- a/src/include/utils/dsa.h +++ b/src/include/utils/dsa.h @@ -161,6 +161,7 @@ extern dsa_pointer dsa_allocate_extended(dsa_area *area, size_t size, int flags) extern void dsa_free(dsa_area *area, dsa_pointer dp); extern void *dsa_get_address(dsa_area *area, dsa_pointer dp); extern size_t dsa_get_total_size(dsa_area *area); +extern size_t dsa_get_total_size_from_handle(dsa_handle handle); extern void dsa_trim(dsa_area *area); extern void dsa_dump(dsa_area *area); diff --git a/src/test/modules/test_dsm_registry/expected/test_dsm_registry.out b/src/test/modules/test_dsm_registry/expected/test_dsm_registry.out index ca8abbb377e..75d9eda0756 100644 --- a/src/test/modules/test_dsm_registry/expected/test_dsm_registry.out +++ b/src/test/modules/test_dsm_registry/expected/test_dsm_registry.out @@ -1,4 +1,4 @@ -SELECT name, type, size IS DISTINCT FROM 0 AS size +SELECT name, type, size > 0 AS size FROM pg_dsm_registry_allocations WHERE name like 'test_dsm_registry%' ORDER BY name; name | type | size @@ -32,7 +32,7 @@ SELECT get_val_in_hash('test'); (1 row) \c -SELECT name, type, size IS DISTINCT FROM 0 AS size +SELECT name, type, size > 0 AS size FROM pg_dsm_registry_allocations WHERE name like 'test_dsm_registry%' ORDER BY name; name | type | size diff --git a/src/test/modules/test_dsm_registry/sql/test_dsm_registry.sql b/src/test/modules/test_dsm_registry/sql/test_dsm_registry.sql index 965a3f1ebb6..1b9ee3ebf18 100644 --- a/src/test/modules/test_dsm_registry/sql/test_dsm_registry.sql +++ b/src/test/modules/test_dsm_registry/sql/test_dsm_registry.sql @@ -1,4 +1,4 @@ -SELECT name, type, size IS DISTINCT FROM 0 AS size +SELECT name, type, size > 0 AS size FROM pg_dsm_registry_allocations WHERE name like 'test_dsm_registry%' ORDER BY name; CREATE EXTENSION test_dsm_registry; @@ -8,6 +8,6 @@ SELECT set_val_in_hash('test', '1414'); SELECT get_val_in_shmem(); SELECT get_val_in_hash('test'); \c -SELECT name, type, size IS DISTINCT FROM 0 AS size +SELECT name, type, size > 0 AS size FROM pg_dsm_registry_allocations WHERE name like 'test_dsm_registry%' ORDER BY name; -- 2.39.5 (Apple Git-154)
