diff options
-rw-r--r-- | src/backend/utils/activity/pgstat.c | 4 | ||||
-rw-r--r-- | src/backend/utils/activity/pgstat_shmem.c | 44 | ||||
-rw-r--r-- | src/include/utils/pgstat_internal.h | 27 |
3 files changed, 62 insertions, 13 deletions
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index 73c2ced3f4e..44621653d8d 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -1487,6 +1487,10 @@ pgstat_register_kind(PgStat_Kind kind, const PgStat_KindInfo *kind_info) ereport(ERROR, (errmsg("custom cumulative statistics property is invalid"), errhint("Custom cumulative statistics require a shared memory size for fixed-numbered objects."))); + if (kind_info->track_entry_count) + ereport(ERROR, + (errmsg("custom cumulative statistics property is invalid"), + errhint("Custom cumulative statistics cannot use entry count tracking for fixed-numbered objects."))); } /* diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c index ca36fd247f6..746e9541bf3 100644 --- a/src/backend/utils/activity/pgstat_shmem.c +++ b/src/backend/utils/activity/pgstat_shmem.c @@ -210,27 +210,35 @@ StatsShmemInit(void) pg_atomic_init_u64(&ctl->gc_request_count, 1); - /* initialize fixed-numbered stats */ + /* Do the per-kind initialization */ for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++) { const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); char *ptr; - if (!kind_info || !kind_info->fixed_amount) + if (!kind_info) continue; - if (pgstat_is_kind_builtin(kind)) - ptr = ((char *) ctl) + kind_info->shared_ctl_off; - else - { - int idx = kind - PGSTAT_KIND_CUSTOM_MIN; + /* initialize entry count tracking */ + if (kind_info->track_entry_count) + pg_atomic_init_u64(&ctl->entry_counts[kind - 1], 0); - Assert(kind_info->shared_size != 0); - ctl->custom_data[idx] = ShmemAlloc(kind_info->shared_size); - ptr = ctl->custom_data[idx]; + /* initialize fixed-numbered stats */ + if (kind_info->fixed_amount) + { + if (pgstat_is_kind_builtin(kind)) + ptr = ((char *) ctl) + kind_info->shared_ctl_off; + else + { + int idx = kind - PGSTAT_KIND_CUSTOM_MIN; + + Assert(kind_info->shared_size != 0); + ctl->custom_data[idx] = ShmemAlloc(kind_info->shared_size); + ptr = ctl->custom_data[idx]; + } + + kind_info->init_shmem_cb(ptr); } - - kind_info->init_shmem_cb(ptr); } } else @@ -303,6 +311,7 @@ pgstat_init_entry(PgStat_Kind kind, /* Create new stats entry. */ dsa_pointer chunk; PgStatShared_Common *shheader; + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); /* * Initialize refcount to 1, marking it as valid / not dropped. The entry @@ -319,7 +328,7 @@ pgstat_init_entry(PgStat_Kind kind, shhashent->dropped = false; chunk = dsa_allocate_extended(pgStatLocal.dsa, - pgstat_get_kind_info(kind)->shared_size, + kind_info->shared_size, DSA_ALLOC_ZERO | DSA_ALLOC_NO_OOM); if (chunk == InvalidDsaPointer) return NULL; @@ -330,6 +339,10 @@ pgstat_init_entry(PgStat_Kind kind, /* Link the new entry from the hash entry. */ shhashent->body = chunk; + /* Increment entry count, if required. */ + if (kind_info->track_entry_count) + pg_atomic_fetch_add_u64(&pgStatLocal.shmem->entry_counts[kind - 1], 1); + LWLockInitialize(&shheader->lock, LWTRANCHE_PGSTATS_DATA); return shheader; @@ -859,6 +872,7 @@ static void pgstat_free_entry(PgStatShared_HashEntry *shent, dshash_seq_status *hstat) { dsa_pointer pdsa; + PgStat_Kind kind = shent->key.kind; /* * Fetch dsa pointer before deleting entry - that way we can free the @@ -872,6 +886,10 @@ pgstat_free_entry(PgStatShared_HashEntry *shent, dshash_seq_status *hstat) dshash_delete_current(hstat); dsa_free(pgStatLocal.dsa, pdsa); + + /* Decrement entry count, if required. */ + if (pgstat_get_kind_info(kind)->track_entry_count) + pg_atomic_sub_fetch_u64(&pgStatLocal.shmem->entry_counts[kind - 1], 1); } /* diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h index bf75ebcef31..88d09ea20ba 100644 --- a/src/include/utils/pgstat_internal.h +++ b/src/include/utils/pgstat_internal.h @@ -232,6 +232,12 @@ typedef struct PgStat_KindInfo bool write_to_file:1; /* + * Should the number of entries be tracked? For variable-numbered stats, + * to update its PgStat_ShmemControl.entry_counts. + */ + bool track_entry_count:1; + + /* * The size of an entry in the shared stats hash table (pointed to by * PgStatShared_HashEntry->body). For fixed-numbered statistics, this is * the size of an entry in PgStat_ShmemControl->custom_data. @@ -501,6 +507,16 @@ typedef struct PgStat_ShmemControl pg_atomic_uint64 gc_request_count; /* + * Counters for the number of entries associated to a single stats kind + * that uses variable-numbered objects stored in the shared hash table. + * These counters can be enabled on a per-kind basis, when + * track_entry_count is set. This counter is incremented each time a new + * entry is created (not reused) in the shared hash table, and is + * decremented each time an entry is freed from the shared hash table. + */ + pg_atomic_uint64 entry_counts[PGSTAT_KIND_MAX]; + + /* * Stats data for fixed-numbered objects. */ PgStatShared_Archiver archiver; @@ -926,6 +942,17 @@ pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry) } /* + * Returns the number of entries counted for a stats kind. + */ +static inline uint64 +pgstat_get_entry_count(PgStat_Kind kind) +{ + Assert(pgstat_get_kind_info(kind)->track_entry_count); + + return pg_atomic_read_u64(&pgStatLocal.shmem->entry_counts[kind - 1]); +} + +/* * Returns a pointer to the shared memory area of custom stats for * fixed-numbered statistics. */ |