agora inbox for pgsql-hackers@postgresql.orghelp / color / mirror / Atom feed
[PATCH v1 2/5] pgstat: add new infrastructure for per-backend statistics 1+ messages / 1 participants [nested] [flat]
* [PATCH v1 2/5] pgstat: add new infrastructure for per-backend statistics @ 2026-07-29 14:11 Bertrand Drouvot <bertranddrouvot.pg@gmail.com> 0 siblings, 0 replies; 1+ messages in thread From: Bertrand Drouvot @ 2026-07-29 14:11 UTC (permalink / raw) Add a new infrastructure for per-backend statistics that keep one shared entry per live backend while keeping their existing shared data as global stats for exited backends. Define a common dshash entry header containing the ProcNumber key, BackendType, and content LWLock. Extend PgStat_KindInfo with per-backend statistics related informations. At shared-memory initialization, create a dshash for every participating kind. Create entries during pgstat_initialize(), so that auxiliary and shared memory only processes are covered. Nonblocking flushes can then acquire the cached entry's content lock without performing a dshash lookup, DSA address resolution, allocation, or hash resize. Add helpers to fetch per-backend entries, include live entries in global snapshots, and transfer entries to the global statistics when backends exit. Add a local cache keyed by statistics kind and ProcNumber for per-backend fetches. No statistics kind registers per backend metadata in this commit, so the new shared memory creation and backend initialization loops are no ops. Subsequent commits will add WAL, Lock, and IO statistics into the infrastructure individually. Limit this infrastructure to built in fixed numbered statistics kinds as this is the only use case we have had so far. We could extend to variable ones later on if needed. Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Reviewed-by: Discussion: --- src/backend/utils/activity/pgstat.c | 506 ++++++++++++++++++++++ src/backend/utils/activity/pgstat_shmem.c | 46 ++ src/include/utils/pgstat_internal.h | 43 ++ src/tools/pgindent/typedefs.list | 4 + 4 files changed, 599 insertions(+) 89.6% src/backend/utils/activity/ 9.6% src/include/utils/ diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index 50cd07822b4..efc7d427f22 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -175,6 +175,41 @@ typedef struct PgStat_SnapshotEntry #define SH_DECLARE #include "lib/simplehash.h" +/* hash table for per-backend stats snapshot entries */ +typedef struct PgStat_PerBackendSnapshotKey +{ + PgStat_Kind kind; + ProcNumber procnum; +} PgStat_PerBackendSnapshotKey; + +typedef struct PgStat_PerBackendSnapshotEntry +{ + PgStat_PerBackendSnapshotKey key; + char status; /* for simplehash use */ + void *data; /* the stats data itself */ +} PgStat_PerBackendSnapshotEntry; + +#define SH_PREFIX pgstat_per_backend_snapshot +#define SH_ELEMENT_TYPE PgStat_PerBackendSnapshotEntry +#define SH_KEY_TYPE PgStat_PerBackendSnapshotKey +#define SH_KEY key +#define SH_HASH_KEY(tb, key) \ + fasthash32((const char *) &key, sizeof(PgStat_PerBackendSnapshotKey), 0) +#define SH_EQUAL(tb, a, b) \ + (memcmp(&a, &b, sizeof(PgStat_PerBackendSnapshotKey)) == 0) +#define SH_SCOPE static inline +#define SH_DEFINE +#define SH_DECLARE +#include "lib/simplehash.h" + +/* Per-kind, backend-local state for the per-backend dshashes. */ +typedef struct PgStat_PerBackendLocalState +{ + dshash_table *hash; + PgStatShared_PerBackendEntry *my_entry; +} PgStat_PerBackendLocalState; + +static PgStat_PerBackendLocalState per_backend_states[PGSTAT_KIND_BUILTIN_SIZE]; /* ---------- * Local function forward declarations @@ -195,6 +230,7 @@ static void pgstat_build_snapshot(void); static void pgstat_build_snapshot_fixed(PgStat_Kind kind); static inline bool pgstat_is_kind_valid(PgStat_Kind kind); +static void pgstat_create_my_per_backend_entries(void); /* ---------- @@ -673,6 +709,13 @@ pgstat_initialize(void) pgstat_attach_shmem(); + /* + * Create and cache per-backend statistics entries here. This also covers + * processes that never call InitPostgres(), such as shared-memory-only + * background workers. + */ + pgstat_create_my_per_backend_entries(); + pgstat_init_snapshot_fixed(); /* Backend initialization callbacks */ @@ -946,6 +989,7 @@ pgstat_clear_snapshot(void) /* Reset variables */ pgStatLocal.snapshot.context = NULL; + pgStatLocal.snapshot.per_backend_stats = NULL; } /* @@ -1161,6 +1205,463 @@ pgstat_prep_snapshot(void) NULL); } +/* + * Look up a per-backend stats entry in the backend snapshot hash. + * + * The returned entry may be empty when no matching statistics were found on + * first access. + */ +static PgStat_PerBackendSnapshotEntry * +pgstat_lookup_per_backend_entry(PgStat_Kind kind, ProcNumber procnum) +{ + PgStat_PerBackendSnapshotKey key; + + if (pgStatLocal.snapshot.per_backend_stats == NULL) + return NULL; + + key.kind = kind; + key.procnum = procnum; + + return pgstat_per_backend_snapshot_lookup(pgStatLocal.snapshot.per_backend_stats, + key); +} + +/* + * Cache a per-backend stats entry in the backend snapshot hash. + * + * If data is NULL, cache an empty entry to record that no matching statistics + * were found on first access. + */ +static void * +pgstat_cache_per_backend_entry(PgStat_Kind kind, ProcNumber procnum, + const void *data) +{ + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + PgStat_PerBackendSnapshotKey key; + PgStat_PerBackendSnapshotEntry *entry; + bool found; + + Assert(pgstat_fetch_consistency > PGSTAT_FETCH_CONSISTENCY_NONE); + Assert(kind_info != NULL); + Assert(kind_info->per_backend_data_len > 0); + + /* Ensure snapshot context exists */ + if (!pgStatLocal.snapshot.context) + pgStatLocal.snapshot.context = AllocSetContextCreate(TopMemoryContext, + "PgStat Snapshot", + ALLOCSET_SMALL_SIZES); + + /* Create per-backend hash on first use */ + if (pgStatLocal.snapshot.per_backend_stats == NULL) + pgStatLocal.snapshot.per_backend_stats = + pgstat_per_backend_snapshot_create(pgStatLocal.snapshot.context, 64, NULL); + + key.kind = kind; + key.procnum = procnum; + + /* If already cached, return cached data */ + entry = pgstat_per_backend_snapshot_lookup(pgStatLocal.snapshot.per_backend_stats, key); + + if (entry) + return entry->data; + + /* Insert new entry into the hash */ + entry = pgstat_per_backend_snapshot_insert(pgStatLocal.snapshot.per_backend_stats, + key, &found); + Assert(!found); + + if (data != NULL) + { + entry->data = MemoryContextAlloc(pgStatLocal.snapshot.context, + kind_info->per_backend_data_len); + memcpy(entry->data, data, kind_info->per_backend_data_len); + } + else + entry->data = NULL; + + return entry->data; +} + +static inline PgStat_PerBackendLocalState * +pgstat_get_per_backend_local_state(PgStat_Kind kind) +{ + const PgStat_KindInfo *kind_info PG_USED_FOR_ASSERTS_ONLY = pgstat_get_kind_info(kind); + + Assert(kind_info != NULL); + Assert(kind_info->fixed_amount); + + if (!pgstat_is_kind_builtin(kind)) + elog(ERROR, "invalid statistics kind: %u", kind); + + return &per_backend_states[kind]; +} + +/* + * Create and cache this process's entry for one per-backend statistics kind. + */ +static PgStatShared_PerBackendEntry * +pgstat_create_my_per_backend_entry(PgStat_Kind kind) +{ + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + PgStat_PerBackendLocalState *state = pgstat_get_per_backend_local_state(kind); + dshash_table *hash = pgstat_per_backend_attach(kind); + PgStatShared_PerBackendEntry *entry; + bool found; + + Assert(state->my_entry == NULL); + + if (hash == NULL) + return NULL; + + Assert(kind_info != NULL); + Assert(kind_info->per_backend_data_len > 0); + + entry = dshash_find_or_insert(hash, &MyProcNumber, &found); + + /* + * A forced flush during early backend startup may already have created + * the entry. Preserve any statistics it contains. + */ + if (!found) + { + entry->backend_type = MyBackendType; + LWLockInitialize(&entry->lock, LWTRANCHE_PGSTATS_DATA); + memset((char *) entry + kind_info->per_backend_data_off, 0, + kind_info->per_backend_data_len); + } + + state->my_entry = entry; + dshash_release_lock(hash, entry); + + return entry; +} + +/* + * Create entries for all the kinds that use per-backend dshashes. + * + * Allocations and dshash resizes are deliberately done during backend + * initialization so routine stats flushes only need to conditionally acquire + * the cached entry's content lock. + */ +static void +pgstat_create_my_per_backend_entries(void) +{ + for (PgStat_Kind kind = PGSTAT_KIND_BUILTIN_MIN; + kind <= PGSTAT_KIND_BUILTIN_MAX; kind++) + { + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + + if (kind_info == NULL || kind_info->per_backend_data_len == 0) + continue; + + (void) pgstat_create_my_per_backend_entry(kind); + } +} + +/* + * Attach to the per-backend dshash for the given kind. + * Returns NULL if the hash is not available (e.g. during bootstrap or + * if this kind doesn't have per-backend tracking). + */ +dshash_table * +pgstat_per_backend_attach(PgStat_Kind kind) +{ + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + PgStat_PerBackendLocalState *state = pgstat_get_per_backend_local_state(kind); + char *shared_struct; + dshash_table_handle *handle_ptr; + MemoryContext oldcontext; + dshash_parameters params; + + if (state->hash != NULL) + return state->hash; + + if (!kind_info || !kind_info->per_backend_data_len) + return NULL; + + /* Get the shared struct for this kind */ + shared_struct = (char *) pgStatLocal.shmem + kind_info->shared_ctl_off; + handle_ptr = (dshash_table_handle *) (shared_struct + kind_info->per_backend_hash_handle_off); + + if (*handle_ptr == DSHASH_HANDLE_INVALID) + return NULL; + + /* + * Build dshash parameters from kind info. All per-backend hashes use + * ProcNumber keys and dshash_memcmp/dshash_memhash. + */ + params.key_size = sizeof(ProcNumber); + params.entry_size = kind_info->per_backend_data_off + kind_info->per_backend_data_len; + params.compare_function = dshash_memcmp; + params.hash_function = dshash_memhash; + params.copy_function = dshash_memcpy; + params.tranche_id = LWTRANCHE_PGSTATS_HASH; + + /* Attach in TopMemoryContext */ + oldcontext = MemoryContextSwitchTo(TopMemoryContext); + state->hash = dshash_attach(pgStatLocal.dsa, ¶ms, *handle_ptr, NULL); + MemoryContextSwitchTo(oldcontext); + + return state->hash; +} + +/* + * Lock this process's cached entry for a per-backend statistics kind. + * + * A missing entry is only created in the blocking path. The routine nowait + * path must not perform dshash lookups, allocations, or DSA address + * resolution. + */ +void * +pgstat_lock_my_per_backend_entry(PgStat_Kind kind, bool nowait) +{ + const PgStat_KindInfo *kind_info PG_USED_FOR_ASSERTS_ONLY = pgstat_get_kind_info(kind); + PgStat_PerBackendLocalState *state = pgstat_get_per_backend_local_state(kind); + PgStatShared_PerBackendEntry *entry = state->my_entry; + + Assert(kind_info != NULL); + Assert(kind_info->per_backend_data_len > 0); + + if (entry == NULL) + { + if (nowait) + return NULL; + + entry = pgstat_create_my_per_backend_entry(kind); + if (entry == NULL) + return NULL; + } + + if (nowait) + { + if (!LWLockConditionalAcquire(&entry->lock, LW_EXCLUSIVE)) + return NULL; + } + else + LWLockAcquire(&entry->lock, LW_EXCLUSIVE); + + return entry; +} + +/* + * Accumulate all live per-backend entries into the kind's data in + * pgStatLocal.snapshot, optionally caching each entry for SNAPSHOT mode. + */ +void +pgstat_per_backend_snapshot(PgStat_Kind kind, dshash_table *hash, void *snap) +{ + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + dshash_seq_status hstat; + PgStatShared_PerBackendEntry *entry; + + dshash_seq_init(&hstat, hash, false); + + while ((entry = dshash_seq_next(&hstat)) != NULL) + { + LWLockAcquire(&entry->lock, LW_SHARED); + + /* Kind-specific accumulation into global snapshot */ + kind_info->per_backend_acc_cb(snap, entry); + + /* + * In SNAPSHOT mode, cache each per-backend entry so that + * pgstat_fetch_per_backend() can return a consistent point-in-time + * view without re-reading from shared memory. + */ + if (pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_SNAPSHOT) + { + pgstat_cache_per_backend_entry(kind, entry->key, + (char *) entry + kind_info->per_backend_data_off); + } + + LWLockRelease(&entry->lock); + } + + dshash_seq_term(&hstat); +} + +/* + * Fetch per-backend stats for the given kind and ProcNumber. + * Returns NULL if no entry exists. In NONE mode, returns a copy allocated in + * the current memory context. In CACHE and SNAPSHOT modes, returns a pointer + * owned by the statistics snapshot cache. + */ +void * +pgstat_fetch_per_backend(PgStat_Kind kind, ProcNumber procnum) +{ + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + dshash_table *hash; + PgStatShared_PerBackendEntry *entry; + void *stats_data; + PgStat_PerBackendSnapshotEntry *snapshot_entry; + + if (force_stats_snapshot_clear) + pgstat_clear_snapshot(); + + hash = pgstat_per_backend_attach(kind); + + if (hash == NULL) + return NULL; + + /* In NONE mode, read directly and don't cache */ + if (pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_NONE) + { + entry = dshash_find(hash, &procnum, false); + if (entry == NULL) + return NULL; + + LWLockAcquire(&entry->lock, LW_SHARED); + stats_data = palloc(kind_info->per_backend_data_len); + memcpy(stats_data, (char *) entry + kind_info->per_backend_data_off, + kind_info->per_backend_data_len); + LWLockRelease(&entry->lock); + dshash_release_lock(hash, entry); + + return stats_data; + } + + Assert(pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_CACHE || + pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_SNAPSHOT); + + /* + * Building a full snapshot pre-caches all existing per-backend entries. + * CACHE mode only needs the requested entry, so it must not build the + * aggregate fixed-kind snapshot and scan every live backend. + */ + if (pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_SNAPSHOT) + pgstat_snapshot_fixed(kind); + + snapshot_entry = pgstat_lookup_per_backend_entry(kind, procnum); + + if (snapshot_entry != NULL) + return snapshot_entry->data; + + /* + * Once a full snapshot has been built, a cache miss means the entry did + * not exist at the snapshot point. Do not admit an entry created later. + */ + if (pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_SNAPSHOT) + return NULL; + + /* CACHE miss: copy the live entry directly into the snapshot context. */ + entry = dshash_find(hash, &procnum, false); + + if (entry == NULL) + return pgstat_cache_per_backend_entry(kind, procnum, NULL); + + LWLockAcquire(&entry->lock, LW_SHARED); + + stats_data = pgstat_cache_per_backend_entry(kind, procnum, + (char *) entry + kind_info->per_backend_data_off); + + LWLockRelease(&entry->lock); + dshash_release_lock(hash, entry); + + return stats_data; +} + +/* + * Accumulate this process's per-backend stats into the global stats, then + * remove the entry from the dshash. + * Acquire the kind lock before the dshash partition lock. Snapshots and resets + * hold the kind lock while accessing both the global stats and live entries, + * so an entry cannot move between them during either operation. + * + * NB: The entry may belong to an earlier process that used the same ProcNumber. + * It must still be accumulated before removal. + */ +void +pgstat_acc_my_per_backend(PgStat_Kind kind, LWLock *lock) +{ + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + PgStat_PerBackendLocalState *state = pgstat_get_per_backend_local_state(kind); + char *shared_struct; + dshash_table *hash; + void *dst; + PgStatShared_PerBackendEntry *entry; + + hash = pgstat_per_backend_attach(kind); + + if (hash == NULL) + return; + + shared_struct = (char *) pgStatLocal.shmem + kind_info->shared_ctl_off; + dst = shared_struct + kind_info->shared_data_off; + + LWLockAcquire(lock, LW_EXCLUSIVE); + + entry = dshash_find(hash, &MyProcNumber, true); + + if (entry == NULL) + { + state->my_entry = NULL; + LWLockRelease(lock); + return; + } + + LWLockAcquire(&entry->lock, LW_EXCLUSIVE); + + if (state->my_entry == entry) + state->my_entry = NULL; + + /* Kind-specific accumulation */ + kind_info->per_backend_acc_cb(dst, entry); + + LWLockRelease(&entry->lock); + + /* Remove the entry */ + dshash_delete_entry(hash, entry); + + LWLockRelease(lock); +} + +/* + * Accumulate all per-backend entries into global stats and delete them. + * Called at clean server shutdown before writing the stats file. Acquire the + * kind's global lock before starting the dshash scan. + */ +void +pgstat_acc_all_per_backend(PgStat_Kind kind, LWLock *lock) +{ + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + PgStat_PerBackendLocalState *state = pgstat_get_per_backend_local_state(kind); + char *shared_struct; + dshash_table *hash; + void *dst; + dshash_seq_status hstat; + PgStatShared_PerBackendEntry *entry; + + hash = pgstat_per_backend_attach(kind); + + if (hash == NULL) + return; + + shared_struct = (char *) pgStatLocal.shmem + kind_info->shared_ctl_off; + dst = shared_struct + kind_info->shared_data_off; + + LWLockAcquire(lock, LW_EXCLUSIVE); + + dshash_seq_init(&hstat, hash, true); + + while ((entry = dshash_seq_next(&hstat)) != NULL) + { + LWLockAcquire(&entry->lock, LW_EXCLUSIVE); + + if (state->my_entry == entry) + state->my_entry = NULL; + + /* Kind-specific accumulation */ + kind_info->per_backend_acc_cb(dst, entry); + + LWLockRelease(&entry->lock); + dshash_delete_current(&hstat); + } + + dshash_seq_term(&hstat); + + LWLockRelease(lock); +} + static void pgstat_build_snapshot(void) { @@ -1540,6 +2041,11 @@ pgstat_register_kind(PgStat_Kind kind, const PgStat_KindInfo *kind_info) errdetail("Custom cumulative statistics must be registered while initializing modules in \"%s\".", "shared_preload_libraries"))); + if (kind_info->per_backend_data_len != 0) + ereport(ERROR, + (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind), + errdetail("Per-backend statistics are not supported for custom cumulative statistics."))); + /* * Check some data for fixed-numbered stats. */ diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c index 8511c25fd29..3b003f00245 100644 --- a/src/backend/utils/activity/pgstat_shmem.c +++ b/src/backend/utils/activity/pgstat_shmem.c @@ -168,6 +168,47 @@ StatsShmemRequest(void *arg) ); } +/* + * Create a dshash for each built-in kind that stores per-backend statistics. + * Derive the entry size and handle location from the kind metadata, just as + * attachment does. + */ +static void +pgstat_create_per_backend_hashes(dsa_area *dsa, PgStat_ShmemControl *ctl) +{ + dshash_parameters params = { + sizeof(ProcNumber), + 0, + dshash_memcmp, + dshash_memhash, + dshash_memcpy, + LWTRANCHE_PGSTATS_HASH + }; + + for (PgStat_Kind kind = PGSTAT_KIND_BUILTIN_MIN; + kind <= PGSTAT_KIND_BUILTIN_MAX; kind++) + { + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + char *shared_struct; + dshash_table_handle *handle_ptr; + dshash_table *dsh; + + if (kind_info == NULL || kind_info->per_backend_data_len == 0) + continue; + + shared_struct = (char *) ctl + kind_info->shared_ctl_off; + handle_ptr = (dshash_table_handle *) + (shared_struct + kind_info->per_backend_hash_handle_off); + + params.entry_size = kind_info->per_backend_data_off + + kind_info->per_backend_data_len; + + dsh = dshash_create(dsa, ¶ms, NULL); + *handle_ptr = dshash_get_hash_table_handle(dsh); + dshash_detach(dsh); + } +} + /* * Initialize cumulative statistics system during startup */ @@ -210,6 +251,11 @@ StatsShmemInit(void *arg) /* lift limit set above */ dsa_set_size_limit(dsa, -1); + /* + * Create per-backend hashes while the local DSA reference is available. + */ + pgstat_create_per_backend_hashes(dsa, ctl); + /* * Postmaster will never access these again, thus free the local * dsa/dshash references. diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h index b0a17691966..340244252c9 100644 --- a/src/include/utils/pgstat_internal.h +++ b/src/include/utils/pgstat_internal.h @@ -380,6 +380,26 @@ typedef struct PgStat_KindInfo */ void (*snapshot_cb) (void); + /* + * Per-backend dshash support for built-in fixed-numbered statistics kinds + * that also maintain per-backend entries in a dedicated dshash. If + * per_backend_data_len is non-zero, the generic infrastructure handles + * attach, fetch, accumulate, and snapshot pre-caching automatically. + * + * Each entry starts with PgStatShared_PerBackendEntry, followed by the + * kind-specific statistics payload. + */ + uint32 per_backend_data_off; /* offset of stats data in entry */ + uint32 per_backend_data_len; /* size of stats data in entry */ + /* offset of dshash_table_handle in shared struct */ + uint32 per_backend_hash_handle_off; + + /* + * Callback to accumulate one per-backend entry into a destination of the + * kind's statistics type. Called with the entry's content lock held. + */ + void (*per_backend_acc_cb) (void *dst, void *entry); + /* name of the kind of stats */ const char *const name; } PgStat_KindInfo; @@ -479,6 +499,17 @@ typedef struct PgStatShared_SLRU PgStat_SLRUStats stats[SLRU_NUM_ELEMENTS]; } PgStatShared_SLRU; +/* + * Common header for entries in per-backend statistics dshashes. The + * ProcNumber key must be the first field for dshash. + */ +typedef struct PgStatShared_PerBackendEntry +{ + ProcNumber key; + BackendType backend_type; + LWLock lock; +} PgStatShared_PerBackendEntry; + typedef struct PgStatShared_Wal { /* lock protects ->stats */ @@ -617,6 +648,9 @@ typedef struct PgStat_Snapshot PgStat_WalStats wal; + /* Per-backend snapshot hash */ + struct pgstat_per_backend_snapshot_hash *per_backend_stats; + /* * Data in snapshot for custom fixed-numbered statistics, indexed by * (PgStat_Kind - PGSTAT_KIND_CUSTOM_MIN). Each entry is allocated in @@ -691,6 +725,15 @@ extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *may_free); extern void pgstat_snapshot_fixed(PgStat_Kind kind); +/* Generic per-backend helpers */ +extern dshash_table *pgstat_per_backend_attach(PgStat_Kind kind); +extern void *pgstat_lock_my_per_backend_entry(PgStat_Kind kind, bool nowait); +extern void pgstat_per_backend_snapshot(PgStat_Kind kind, dshash_table *hash, + void *snap); +extern void *pgstat_fetch_per_backend(PgStat_Kind kind, ProcNumber procnum); +extern void pgstat_acc_my_per_backend(PgStat_Kind kind, LWLock *lock); +extern void pgstat_acc_all_per_backend(PgStat_Kind kind, LWLock *lock); + /* * Functions in pgstat_archiver.c diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 85d989f395d..0b7dbc42e80 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -2327,6 +2327,7 @@ PgStatShared_Function PgStatShared_HashEntry PgStatShared_IO PgStatShared_Lock +PgStatShared_PerBackendEntry PgStatShared_Relation PgStatShared_ReplSlot PgStatShared_SLRU @@ -2351,6 +2352,9 @@ PgStat_KindInfo PgStat_LocalState PgStat_Lock PgStat_LockEntry +PgStat_PerBackendLocalState +PgStat_PerBackendSnapshotEntry +PgStat_PerBackendSnapshotKey PgStat_PendingDroppedStatsItem PgStat_PendingIO PgStat_PendingLock -- 2.34.1 --Hx3mnhNtand64WhS Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0003-pgstat-move-WAL-statistics-to-new-per-backend-inf.patch" ^ permalink raw reply [nested|flat] 1+ messages in thread
only message in thread Thread overview: 1+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2026-07-29 14:11 [PATCH v1 2/5] pgstat: add new infrastructure for per-backend statistics Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox