]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Merge init and max size options on shmem hash tables
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 3 Apr 2026 23:40:20 +0000 (02:40 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 3 Apr 2026 23:40:20 +0000 (02:40 +0300)
Replace the separate init and max size options with a single size
option. We didn't make much use of the feature, all callers except the
ones in wait_event.c already used the same size for both, and the hash
tables in wait_event.c are small so there's little harm in just
allocating them to the max size.

The only reason why you might want to not reserve the max size upfront
is to make the memory available for other hash tables to grow beyond
their max size. Letting hash tables grow much beyond their max size is
bad for performance, however, because we cannot resize the directory,
and we never had very much "wiggle room" to grow to anyway so you
couldn't really rely on it. We recently marked the LOCK and PROCLOCK
tables with HAS_FIXED_SIZE, so there's nothing left in core that would
benefit from more unallocated shared memory.

Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://www.postgresql.org/message-id/01ab1d41-3eda-4705-8bbd-af898f5007f1@iki.fi

contrib/pg_stat_statements/pg_stat_statements.c
src/backend/storage/buffer/buf_table.c
src/backend/storage/ipc/shmem.c
src/backend/storage/lmgr/lock.c
src/backend/storage/lmgr/predicate.c
src/backend/utils/activity/wait_event.c
src/include/storage/shmem.h

index 7975476b8909dfa8f58004be075772166767f9d4..5494d41dca16121ee99ef7d0c22f2262458172ce 100644 (file)
@@ -561,7 +561,7 @@ pgss_shmem_startup(void)
        info.keysize = sizeof(pgssHashKey);
        info.entrysize = sizeof(pgssEntry);
        pgss_hash = ShmemInitHash("pg_stat_statements hash",
-                                                         pgss_max, pgss_max,
+                                                         pgss_max,
                                                          &info,
                                                          HASH_ELEM | HASH_BLOBS);
 
index 23d85fd32e2c91eb579ea7744b2f42e76ce4082a..d04ef74b850cda94978522f53f83afbb82e05032 100644 (file)
@@ -60,7 +60,7 @@ InitBufTable(int size)
        info.num_partitions = NUM_BUFFER_PARTITIONS;
 
        SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
-                                                                 size, size,
+                                                                 size,
                                                                  &info,
                                                                  HASH_ELEM | HASH_BLOBS | HASH_PARTITION | HASH_FIXED_SIZE);
 }
index a5b7360e2dc8335156d4df4aa31de5193d87bd80..85757a35823a558773b885fbb89a6fb3e670c606 100644 (file)
@@ -330,14 +330,7 @@ ShmemAddrIsValid(const void *addr)
  * table at once.  (In practice, all creations are done in the postmaster
  * process; child processes should always be attaching to existing tables.)
  *
- * max_size is the estimated maximum number of hashtable entries.  This is
- * not a hard limit, but the access efficiency will degrade if it is
- * exceeded substantially (since it's used to compute directory size and
- * the hash table buckets will get overfull).
- *
- * init_size is the number of hashtable entries to preallocate.  For a table
- * whose maximum size is certain, this should be equal to max_size; that
- * ensures that no run-time out-of-shared-memory failures can occur.
+ * nelems is the maximum number of hashtable entries.
  *
  * *infoP and hash_flags must specify at least the entry sizes and key
  * comparison semantics (see hash_create()).  Flag bits and values specific
@@ -350,8 +343,7 @@ ShmemAddrIsValid(const void *addr)
  */
 HTAB *
 ShmemInitHash(const char *name,                /* table string name for shmem index */
-                         int64 init_size,      /* initial table size */
-                         int64 max_size,       /* max size of the table */
+                         int64 nelems,         /* size of the table */
                          HASHCTL *infoP,       /* info about key and bucket size */
                          int hash_flags)       /* info about infoP */
 {
@@ -365,7 +357,7 @@ ShmemInitHash(const char *name,             /* table string name for shmem index */
         *
         * The shared memory allocator must be specified too.
         */
-       infoP->dsize = infoP->max_dsize = hash_select_dirsize(max_size);
+       infoP->dsize = infoP->max_dsize = hash_select_dirsize(nelems);
        infoP->alloc = ShmemHashAlloc;
        infoP->alloc_arg = NULL;
        hash_flags |= HASH_SHARED_MEM | HASH_ALLOC | HASH_DIRSIZE;
@@ -385,7 +377,7 @@ ShmemInitHash(const char *name,             /* table string name for shmem index */
        /* Pass location of hashtable header to hash_create */
        infoP->hctl = (HASHHDR *) location;
 
-       return hash_create(name, init_size, infoP, hash_flags);
+       return hash_create(name, nelems, infoP, hash_flags);
 }
 
 /*
index aa0f7bf4a1c7339e18d879a1ec98d7dad72a6ce3..9dae407981f65007f42a6620a41f57bec7011497 100644 (file)
@@ -463,7 +463,6 @@ LockManagerShmemInit(void)
        info.num_partitions = NUM_LOCK_PARTITIONS;
 
        LockMethodLockHash = ShmemInitHash("LOCK hash",
-                                                                          max_table_size,
                                                                           max_table_size,
                                                                           &info,
                                                                           HASH_ELEM | HASH_BLOBS |
@@ -482,7 +481,6 @@ LockManagerShmemInit(void)
        info.num_partitions = NUM_LOCK_PARTITIONS;
 
        LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
-                                                                                  max_table_size,
                                                                                   max_table_size,
                                                                                   &info,
                                                                                   HASH_ELEM | HASH_FUNCTION |
index efa47ec16846ed672ed3fac7a00ac42bc634556d..e003fa5b107536f630cc4b1f58998411773d0711 100644 (file)
@@ -1182,7 +1182,6 @@ PredicateLockShmemInit(void)
        info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;
 
        PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
-                                                                                       max_predicate_lock_targets,
                                                                                        max_predicate_lock_targets,
                                                                                        &info,
                                                                                        HASH_ELEM | HASH_BLOBS |
@@ -1218,7 +1217,6 @@ PredicateLockShmemInit(void)
        max_predicate_locks = max_predicate_lock_targets * 2;
 
        PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
-                                                                         max_predicate_locks,
                                                                          max_predicate_locks,
                                                                          &info,
                                                                          HASH_ELEM | HASH_FUNCTION |
@@ -1297,7 +1295,6 @@ PredicateLockShmemInit(void)
        info.entrysize = sizeof(SERIALIZABLEXID);
 
        SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
-                                                                               max_serializable_xacts,
                                                                                max_serializable_xacts,
                                                                                &info,
                                                                                HASH_ELEM | HASH_BLOBS |
index e5a2289f0b074f790938199d0f2048b3875f529a..2b76967776c9084e108d67fabea20b14ec115d2e 100644 (file)
@@ -56,16 +56,14 @@ uint32         *my_wait_event_info = &local_my_wait_event_info;
  * For simplicity, we use the same ID counter across types of custom events.
  * We could end that anytime the need arises.
  *
- * The size of the hash table is based on the assumption that
- * WAIT_EVENT_CUSTOM_HASH_INIT_SIZE is enough for most cases, and it seems
- * unlikely that the number of entries will reach
- * WAIT_EVENT_CUSTOM_HASH_MAX_SIZE.
+ * The size of the hash table is based on the assumption that usually only a
+ * handful of entries are needed, but since it's small in absolute terms
+ * anyway, we leave a generous amount of headroom.
  */
 static HTAB *WaitEventCustomHashByInfo; /* find names from infos */
 static HTAB *WaitEventCustomHashByName; /* find infos from names */
 
-#define WAIT_EVENT_CUSTOM_HASH_INIT_SIZE       16
-#define WAIT_EVENT_CUSTOM_HASH_MAX_SIZE        128
+#define WAIT_EVENT_CUSTOM_HASH_SIZE    128
 
 /* hash table entries */
 typedef struct WaitEventCustomEntryByInfo
@@ -106,9 +104,9 @@ WaitEventCustomShmemSize(void)
        Size            sz;
 
        sz = MAXALIGN(sizeof(WaitEventCustomCounterData));
-       sz = add_size(sz, hash_estimate_size(WAIT_EVENT_CUSTOM_HASH_MAX_SIZE,
+       sz = add_size(sz, hash_estimate_size(WAIT_EVENT_CUSTOM_HASH_SIZE,
                                                                                 sizeof(WaitEventCustomEntryByInfo)));
-       sz = add_size(sz, hash_estimate_size(WAIT_EVENT_CUSTOM_HASH_MAX_SIZE,
+       sz = add_size(sz, hash_estimate_size(WAIT_EVENT_CUSTOM_HASH_SIZE,
                                                                                 sizeof(WaitEventCustomEntryByName)));
        return sz;
 }
@@ -138,8 +136,7 @@ WaitEventCustomShmemInit(void)
        info.entrysize = sizeof(WaitEventCustomEntryByInfo);
        WaitEventCustomHashByInfo =
                ShmemInitHash("WaitEventCustom hash by wait event information",
-                                         WAIT_EVENT_CUSTOM_HASH_INIT_SIZE,
-                                         WAIT_EVENT_CUSTOM_HASH_MAX_SIZE,
+                                         WAIT_EVENT_CUSTOM_HASH_SIZE,
                                          &info,
                                          HASH_ELEM | HASH_BLOBS);
 
@@ -148,8 +145,7 @@ WaitEventCustomShmemInit(void)
        info.entrysize = sizeof(WaitEventCustomEntryByName);
        WaitEventCustomHashByName =
                ShmemInitHash("WaitEventCustom hash by name",
-                                         WAIT_EVENT_CUSTOM_HASH_INIT_SIZE,
-                                         WAIT_EVENT_CUSTOM_HASH_MAX_SIZE,
+                                         WAIT_EVENT_CUSTOM_HASH_SIZE,
                                          &info,
                                          HASH_ELEM | HASH_STRINGS);
 }
@@ -238,7 +234,7 @@ WaitEventCustomNew(uint32 classId, const char *wait_event_name)
        /* Allocate a new event Id */
        SpinLockAcquire(&WaitEventCustomCounter->mutex);
 
-       if (WaitEventCustomCounter->nextId >= WAIT_EVENT_CUSTOM_HASH_MAX_SIZE)
+       if (WaitEventCustomCounter->nextId >= WAIT_EVENT_CUSTOM_HASH_SIZE)
        {
                SpinLockRelease(&WaitEventCustomCounter->mutex);
                ereport(ERROR,
index 2a9e9becd260d7aee0bbd7cf8a0920a9276c55d1..0ae609aca8b9a5d5bd27ec3f3776f18fa956518e 100644 (file)
@@ -32,7 +32,7 @@ extern void InitShmemAllocator(PGShmemHeader *seghdr);
 extern void *ShmemAlloc(Size size);
 extern void *ShmemAllocNoError(Size size);
 extern bool ShmemAddrIsValid(const void *addr);
-extern HTAB *ShmemInitHash(const char *name, int64 init_size, int64 max_size,
+extern HTAB *ShmemInitHash(const char *name, int64 nelems,
                                                   HASHCTL *infoP, int hash_flags);
 extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr);
 extern Size add_size(Size s1, Size s2);