public inbox for [email protected]help / color / mirror / Atom feed
[PATCH v2] Fix various shared memory estimates. 25+ messages / 2 participants [nested] [flat]
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* [PATCH v2] Fix various shared memory estimates. @ 2021-02-27 07:45 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Julien Rouhaud @ 2021-02-27 07:45 UTC (permalink / raw) --- contrib/pg_prewarm/autoprewarm.c | 2 +- .../pg_stat_statements/pg_stat_statements.c | 2 +- src/backend/access/common/syncscan.c | 2 +- src/backend/access/nbtree/nbtutils.c | 3 +- src/backend/access/transam/multixact.c | 2 +- src/backend/access/transam/slru.c | 2 +- src/backend/access/transam/twophase.c | 2 +- src/backend/access/transam/xlog.c | 2 +- src/backend/commands/async.c | 1 + src/backend/postmaster/autovacuum.c | 3 +- src/backend/postmaster/bgworker.c | 2 +- src/backend/postmaster/checkpointer.c | 2 +- src/backend/postmaster/pgstat.c | 17 ++--- src/backend/postmaster/postmaster.c | 2 +- src/backend/replication/logical/launcher.c | 3 +- src/backend/replication/logical/origin.c | 3 +- src/backend/replication/slot.c | 2 +- src/backend/replication/walreceiverfuncs.c | 2 +- src/backend/replication/walsender.c | 2 +- src/backend/storage/buffer/buf_init.c | 14 ++-- src/backend/storage/buffer/buf_table.c | 3 +- src/backend/storage/buffer/freelist.c | 2 +- src/backend/storage/ipc/dsm.c | 2 +- src/backend/storage/ipc/pmsignal.c | 2 +- src/backend/storage/ipc/procarray.c | 8 +-- src/backend/storage/ipc/procsignal.c | 2 +- src/backend/storage/ipc/sinvaladt.c | 2 +- src/backend/storage/lmgr/lock.c | 16 ++++- src/backend/storage/lmgr/lwlock.c | 2 +- src/backend/storage/lmgr/predicate.c | 22 +++--- src/backend/storage/lmgr/proc.c | 12 ++-- src/backend/utils/hash/dynahash.c | 69 ++++++++++++++----- src/backend/utils/time/snapmgr.c | 2 +- src/include/storage/predicate_internals.h | 4 +- src/include/storage/shmem.h | 13 ++++ src/include/utils/hsearch.h | 2 + 36 files changed, 146 insertions(+), 87 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index b3f73ea92d..887e68b288 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -138,7 +138,7 @@ _PG_init(void) EmitWarningsOnPlaceholders("pg_prewarm"); - RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState))); + RequestAddinShmemSpace(CACHELINEALIGN(sizeof(AutoPrewarmSharedState))); /* Register autoprewarm worker, if enabled. */ if (autoprewarm) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 62cccbfa44..4e045ffba7 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,7 +1933,7 @@ pgss_memsize(void) { Size size; - size = MAXALIGN(sizeof(pgssSharedState)); + size = CACHELINEALIGN(sizeof(pgssSharedState)); size = add_size(size, hash_estimate_size(pgss_max, sizeof(pgssEntry))); return size; diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index b7a28af4ad..c19f9cab59 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -125,7 +125,7 @@ static BlockNumber ss_search(RelFileNode relfilenode, Size SyncScanShmemSize(void) { - return SizeOfScanLocations(SYNC_SCAN_NELEM); + return (Size) CACHELINEALIGN(SizeOfScanLocations(SYNC_SCAN_NELEM)); } /* diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d524310723..310ea904df 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -2066,7 +2066,8 @@ BTreeShmemSize(void) size = offsetof(BTVacInfo, vacuums); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 1f9f1a1fa1..c789623c34 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1830,7 +1830,7 @@ MultiXactShmemSize(void) add_size(offsetof(MultiXactStateData, perBackendXactIds) + sizeof(MultiXactId), \ mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) - size = SHARED_MULTIXACT_STATE_SIZE; + size = CACHELINEALIGN(SHARED_MULTIXACT_STATE_SIZE); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 82149ad782..2271e092e9 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -168,7 +168,7 @@ SimpleLruShmemSize(int nslots, int nlsns) if (nlsns > 0) sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */ - return BUFFERALIGN(sz) + BLCKSZ * nslots; + return (Size) CACHELINEALIGN(BUFFERALIGN(sz) + BLCKSZ * nslots); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 80d2d20d6c..fca70fabac 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -245,7 +245,7 @@ TwoPhaseShmemSize(void) size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 377afb8732..64de453340 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -5096,7 +5096,7 @@ XLOGShmemSize(void) * routine again below to compute the actual allocation size. */ - return size; + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 4b16fb5682..6a0fd6ca10 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -513,6 +513,7 @@ AsyncShmemSize(void) /* This had better match AsyncShmemInit */ size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); + size = (Size) CACHELINEALIGN(size); size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 23ef23c13e..7ddf86af74 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3414,7 +3414,8 @@ AutoVacuumShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(autovacuum_max_workers, sizeof(WorkerInfoData))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index bbbc09b0b5..d2f838eaed 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -148,7 +148,7 @@ BackgroundWorkerShmemSize(void) size = add_size(size, mul_size(max_worker_processes, sizeof(BackgroundWorkerSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 76f9f98ebb..6acd5e4c2b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -862,7 +862,7 @@ CheckpointerShmemSize(void) size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index f75b52719d..b08f7f1d56 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2930,25 +2930,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); + size = mul_size_and_shmem_align(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ - size = add_size(size, - mul_size(NAMEDATALEN, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ - size = add_size(size, - mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif #ifdef ENABLE_GSS /* BackendGssStatusBuffer: */ - size = add_size(size, - mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); + size = add_shmem_aligned_size(size, mul_size(sizeof(PgBackendGSSStatus), NumBackendStatSlots)); #endif return size; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index edab95a19e..716f7434e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -6425,7 +6425,7 @@ restore_backend_variables(BackendParameters *param, Port *port) Size ShmemBackendArraySize(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); + return mul_size_and_shmem_align(MaxLivePostmasterChildren(), sizeof(Backend)); } void diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index cb462a052a..7d20877920 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -697,7 +697,8 @@ ApplyLauncherShmemSize(void) size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); - return size; + + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 39471fddad..b9e9fa121a 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -503,7 +503,8 @@ ReplicationOriginShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationState))); - return size; + + return (Size) CACHELINEALIGN(size); } void diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 75a087c2f9..c399c491e9 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -124,7 +124,7 @@ ReplicationSlotsShmemSize(void) size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 63e60478ea..a8cab3fa28 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -45,7 +45,7 @@ WalRcvShmemSize(void) size = add_size(size, sizeof(WalRcvData)); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walreceiver-related shared memory */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 23baa4498a..d1c91cf354 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -3055,7 +3055,7 @@ WalSndShmemSize(void) size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); - return size; + return (Size) CACHELINEALIGN(size); } /* Allocate and initialize walsender-related shared memory */ diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index e9e4f35bb5..b92fdeef14 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -159,15 +159,13 @@ BufferShmemSize(void) Size size = 0; /* size of buffer descriptors */ - size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); - /* to allow aligning buffer descriptors */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* size of data pages */ - size = add_size(size, mul_size(NBuffers, BLCKSZ)); + size = add_shmem_aligned_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ - size = add_size(size, StrategyShmemSize()); + size = add_shmem_aligned_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that @@ -178,12 +176,10 @@ BufferShmemSize(void) * locks are not highly contended, we lay out the array with minimal * padding. */ - size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); - /* to allow aligning the above */ - size = add_size(size, PG_CACHE_LINE_SIZE); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* size of checkpoint sort array in bufmgr.c */ - size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); + size = add_shmem_aligned_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; } diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index caa03ae123..4200f99340 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -41,7 +41,8 @@ static HTAB *SharedBufHash; Size BufTableShmemSize(int size) { - return hash_estimate_size(size, sizeof(BufferLookupEnt)); + return hash_estimate_size_ext(size, sizeof(BufferLookupEnt), + size, true); } /* diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..33e9e74f40 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -459,7 +459,7 @@ StrategyShmemSize(void) size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS)); /* size of the shared replacement strategy control block */ - size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl))); + size = add_shmem_aligned_size(size, sizeof(BufferStrategyControl)); return size; } diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b461a5f7e9..6ecf195c55 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -440,7 +440,7 @@ dsm_set_control_handle(dsm_handle h) size_t dsm_estimate_size(void) { - return 1024 * 1024 * (size_t) min_dynamic_shared_memory; + return (size_t) CACHELINEALIGN(1024 * 1024 * min_dynamic_shared_memory); } /* diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 280c2395c9..d25080224a 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -124,7 +124,7 @@ PMSignalShmemSize(void) size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4fc6ffb917..9b804f1152 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -358,6 +358,7 @@ ProcArrayShmemSize(void) size = offsetof(ProcArrayStruct, pgprocnos); size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS)); + size = CACHELINEALIGN(size); /* * During Hot Standby processing we have a data structure called @@ -377,11 +378,8 @@ ProcArrayShmemSize(void) if (EnableHotStandby) { - size = add_size(size, - mul_size(sizeof(TransactionId), - TOTAL_MAX_CACHED_SUBXIDS)); - size = add_size(size, - mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS)); + size = add_shmem_aligned_size(size, mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS)); } return size; diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index c6a8d4611e..2af7f3e343 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -113,7 +113,7 @@ ProcSignalShmemSize(void) size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot)); size = add_size(size, offsetof(ProcSignalHeader, psh_slot)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 946bd8e3cb..8379bf12e7 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -207,7 +207,7 @@ SInvalShmemSize(void) size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 108b4d9023..f2fc8af5c5 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -54,7 +54,7 @@ int max_locks_per_xact; /* set by guc.c */ #define NLOCKENTS() \ - mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) + mul_size_and_shmem_align(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) /* @@ -3527,17 +3527,27 @@ LockShmemSize(void) /* lock hash table */ max_table_size = NLOCKENTS(); - size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(LOCK), + max_table_size / 2, + true)); /* proclock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, sizeof(PROCLOCK), + max_table_size / 2, + true)); /* * Since NLOCKENTS is only an estimate, add 10% safety margin. */ size = add_size(size, size / 10); + /* + * Note: we don't count fast-path structure, it comes out of the "slop + * factor" added by CreateSharedMemoryAndSemaphores. This lets us use this + * routine again below to compute the actual allocation size. + */ + return size; } diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 8cb6a6f042..6a47918616 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -456,7 +456,7 @@ LWLockShmemSize(void) /* Disallow adding any more named tranches. */ lock_named_request_allowed = false; - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index d493aeef0f..1dcadc00ae 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1359,13 +1359,17 @@ PredicateLockShmemSize(void) /* predicate lock target hash table */ max_table_size = NPREDICATELOCKTARGETENTS(); - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCKTARGET))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCKTARGET), + max_table_size, + true)); /* predicate lock hash table */ max_table_size *= 2; - size = add_size(size, hash_estimate_size(max_table_size, - sizeof(PREDICATELOCK))); + size = add_size(size, hash_estimate_size_ext(max_table_size, + sizeof(PREDICATELOCK), + max_table_size, + true)); /* * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety @@ -1377,8 +1381,7 @@ PredicateLockShmemSize(void) max_table_size = MaxBackends + max_prepared_xacts; max_table_size *= 10; size = add_size(size, PredXactListDataSize); - size = add_size(size, mul_size((Size) max_table_size, - PredXactListElementDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, PredXactListElementDataSize)); /* transaction xid table */ size = add_size(size, hash_estimate_size(max_table_size, @@ -1387,14 +1390,13 @@ PredicateLockShmemSize(void) /* rw-conflict pool */ max_table_size *= 5; size = add_size(size, RWConflictPoolHeaderDataSize); - size = add_size(size, mul_size((Size) max_table_size, - RWConflictDataSize)); + size = add_shmem_aligned_size(size, mul_size((Size) max_table_size, RWConflictDataSize)); /* Head for list of finished serializable transactions. */ - size = add_size(size, sizeof(SHM_QUEUE)); + size = add_shmem_aligned_size(size, sizeof(SHM_QUEUE)); /* Shared memory structures for SLRU tracking of old committed xids. */ - size = add_size(size, sizeof(SerialControlData)); + size = add_shmem_aligned_size(size, sizeof(SerialControlData)); size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); return size; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 897045ee27..28031c7d22 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -106,13 +106,13 @@ ProcGlobalShmemSize(void) add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ - size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); - size = add_size(size, sizeof(slock_t)); + size = add_shmem_aligned_size(size, sizeof(PROC_HDR)); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_shmem_aligned_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_shmem_aligned_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); return size; } diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 6546e3c7c7..030ca3917c 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -769,23 +769,43 @@ init_htab(HTAB *hashp, long nelem) return true; } +/* + * Wrapper around hash_estimate_size for non partitioned hash table and all + * entries preallocated. + */ +Size +hash_estimate_size(long num_entries, Size entrysize) +{ + return hash_estimate_size_ext(num_entries, entrysize, num_entries, false); +} + /* * Estimate the space needed for a hashtable containing the given number - * of entries of given size. + * of entries of given size, and given it's partitioned or not. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size -hash_estimate_size(long num_entries, Size entrysize) +hash_estimate_size_ext(long num_entries, Size entrysize, long init_entries, + bool partitioned) { - Size size; + Size size, + segmentSize, + freelistAllocSize; long nBuckets, nSegments, nDirEntries, - nElementAllocs, elementSize, - elementAllocCnt; + nelemFreelist; + int nFreelists; + + if (partitioned) + nFreelists = NUM_FREELISTS; + else + nFreelists = 1; + + Assert(init_entries <= num_entries); /* estimate number of buckets wanted */ nBuckets = next_pow2_long(num_entries); @@ -797,19 +817,36 @@ hash_estimate_size(long num_entries, Size entrysize) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ - size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ + size = CACHELINEALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ - size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); + size = add_shmem_aligned_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ - size = add_size(size, mul_size(nSegments, - MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); - /* elements --- allocated in groups of choose_nelem_alloc() entries */ - elementAllocCnt = choose_nelem_alloc(entrysize); - nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; + segmentSize = CACHELINEALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)); + size = add_size(size, mul_size(nSegments, segmentSize)); + elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); - size = add_size(size, - mul_size(nElementAllocs, - mul_size(elementAllocCnt, elementSize))); + + /* + * elements --- allocated in groups of choose_nelem_alloc() entries, except + * for the first init_entries, allocated in num_freelists groups. + */ + nelemFreelist = init_entries / nFreelists; + freelistAllocSize = mul_size_and_shmem_align(nelemFreelist, elementSize); + + size = add_size(size, mul_size(nFreelists, freelistAllocSize)); + + if (num_entries > init_entries) + { + Size nelem, + nAlloc, + allocSize; + + nelem = choose_nelem_alloc(entrysize); + nAlloc = (num_entries - init_entries - 1) / nelem + 1; + allocSize = mul_size_and_shmem_align(nelem, elementSize); + + size = add_size(size, mul_size(nAlloc, allocSize)); + } return size; } @@ -852,7 +889,7 @@ hash_get_shared_size(HASHCTL *info, int flags) { Assert(flags & HASH_DIRSIZE); Assert(info->dsize == info->max_dsize); - return sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT); + return (Size) CACHELINEALIGN(sizeof(HASHHDR) + info->dsize * sizeof(HASHSEGMENT)); } diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 95704265b6..b66278e466 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -203,7 +203,7 @@ SnapMgrShmemSize(void) size = add_size(size, mul_size(sizeof(TransactionId), OLD_SNAPSHOT_TIME_MAP_ENTRIES)); - return size; + return (Size) CACHELINEALIGN(size); } /* diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index 104f560d38..bbc6ca4cbf 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -192,7 +192,7 @@ typedef struct PredXactListData typedef struct PredXactListData *PredXactList; #define PredXactListDataSize \ - ((Size)MAXALIGN(sizeof(PredXactListData))) + ((Size)CACHELINEALIGN(sizeof(PredXactListData))) /* @@ -227,7 +227,7 @@ typedef struct RWConflictPoolHeaderData typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader; #define RWConflictPoolHeaderDataSize \ - ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData))) + ((Size)CACHELINEALIGN(sizeof(RWConflictPoolHeaderData))) /* diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 31024e5a50..897672bc8e 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -45,6 +45,19 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +/* + * Macro around add_size and mul_size to account for extra padding as done in + * ShmemAlloc(). + * + * add_shmem_aligned_size() will add the padding bytes to the 2nd argument + * mul_size_and_shmem_align will return the aligned size + */ +#define add_shmem_aligned_size(s1, s2) add_size((s1), \ + (Size) CACHELINEALIGN(s2)) + +#define mul_size_and_shmem_align(s1, s2) add_shmem_aligned_size(0, \ + mul_size((s1), (s2))) + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index d7af0239c8..20c0ff3036 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -145,6 +145,8 @@ extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); extern Size hash_estimate_size(long num_entries, Size entrysize); +extern Size hash_estimate_size_ext(long num_entries, Size entrysize, + long init_entries, bool num_freelists); extern long hash_select_dirsize(long num_entries); extern Size hash_get_shared_size(HASHCTL *info, int flags); extern void AtEOXact_HashTables(bool isCommit); -- 2.30.1 --qghjt52pj73pl6gt-- ^ permalink raw reply [nested|flat] 25+ messages in thread
* Re: Custom explain options @ 2023-11-29 20:03 Pavel Stehule <[email protected]> 0 siblings, 0 replies; 25+ messages in thread From: Pavel Stehule @ 2023-11-29 20:03 UTC (permalink / raw) To: Konstantin Knizhnik <[email protected]>; +Cc: pgsql-hackers Hi so 25. 11. 2023 v 8:23 odesÃlatel Konstantin Knizhnik <[email protected]> napsal: > Hi hackers, > > EXPLAIN statement has a list of options (i.e. ANALYZE, BUFFERS, COST,...) > which help to provide useful details of query execution. > In Neon we have added PREFETCH option which shows information about page > prefetching during query execution (prefetching is more critical for Neon > architecture because of separation of compute and storage, so it is > implemented not only for bitmap heap scan as in Vanilla Postgres, but also > for seqscan, indexscan and indexonly scan). Another possible candidate for > explain options is local file cache (extra caching layer above shared > buffers which is used to somehow replace file system cache in standalone > Postgres). > > I think that it will be nice to have a generic mechanism which allows > extensions to add its own options to EXPLAIN. > I have attached the patch with implementation of such mechanism (also > available as PR: https://github.com/knizhnik/postgres/pull/1 ) > > I have demonstrated this mechanism using Bloom extension - just to report > number of Bloom matches. > Not sure that it is really useful information but it is used mostly as > example: > > explain (analyze,bloom) select * from t where pk=2000; > QUERY PLAN > ------------------------------------------------------------------------------------------------------------------------- > Bitmap Heap Scan on t (cost=15348.00..15352.01 rows=1 width=4) (actual time=25.244..25.939 rows=1 loops=1) > Recheck Cond: (pk = 2000) > Rows Removed by Index Recheck: 292 > Heap Blocks: exact=283 > Bloom: matches=293 > -> Bitmap Index Scan on t_pk_idx (cost=0.00..15348.00 rows=1 width=0) (actual time=25.147..25.147 rows=293 loops=1) > Index Cond: (pk = 2000) > Bloom: matches=293 > Planning: > Bloom: matches=0 > Planning Time: 0.387 ms > Execution Time: 26.053 ms > (12 rows) > > There are two known issues with this proposal: > > 1. I have to limit total size of all custom metrics - right now it is > limited by 128 bytes. It is done to keep Instrumentation and some other > data structures fixes size. Otherwise maintaining varying parts of this > structure is ugly, especially in shared memory > > 2. Custom extension is added by means of RegisterCustomInsrumentation function > which is called from _PG_init > But _PG_init is called when extension is loaded and it is loaded on > demand when some of extension functions is called (except when extension is > included > in shared_preload_libraries list), Bloom extension doesn't require it. So > if your first statement executed in your session is: > > explain (analyze,bloom) select * from t where pk=2000; > > ...you will get error: > > ERROR: unrecognized EXPLAIN option "bloom" > LINE 1: explain (analyze,bloom) select * from t where pk=2000; > > It happens because at the moment when explain statement parses options, > Bloom index is not yet selected and so bloom extension is not loaded and > RegisterCustomInsrumentation is not yet called. If we repeat the query, > then proper result will be displayed (see above). > > This patch has a lot of whitespaces and formatting issues. I fixed some I don't understand how selecting some custom instrumentation can be safe. List *pgCustInstr is a global variable. The attribute selected is set by NewExplainState routine + /* Reset custom instrumentations selection flag */ + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + + ci->selected = false; + } and this attribute is used more times. But the queries can be nested. Theoretically EXPLAIN ANALYZE can run another EXPLAIN ANALYZE, and then this attribute of the global list can be rewritten. The list of selected custom instrumentations should be part of explain state, I think. Regards Pavel Attachments: [text/x-patch] v20231129-0002-fix-whitespaces-and-formatting.patch (14.4K, ../../CAFj8pRDXQX9F+wDVPuBdM2UGDvxfLY5Pf1=dtk2x2=7GUBPsqA@mail.gmail.com/3-v20231129-0002-fix-whitespaces-and-formatting.patch) download | inline diff: From fcc48bee889e4a052ba20f10f08d7f5b5eeaa43f Mon Sep 17 00:00:00 2001 From: "[email protected]" <[email protected]> Date: Wed, 29 Nov 2023 07:51:51 +0100 Subject: [PATCH 2/2] fix whitespaces and formatting --- contrib/bloom/blscan.c | 1 + contrib/bloom/blutils.c | 21 +++++--- src/backend/access/nbtree/nbtsort.c | 7 +-- src/backend/commands/explain.c | 17 ++++--- src/backend/commands/vacuumparallel.c | 5 +- src/backend/executor/execParallel.c | 5 +- src/backend/executor/instrument.c | 72 ++++++++++++++++----------- 7 files changed, 79 insertions(+), 49 deletions(-) diff --git a/contrib/bloom/blscan.c b/contrib/bloom/blscan.c index 8890951943..7fc43f174d 100644 --- a/contrib/bloom/blscan.c +++ b/contrib/bloom/blscan.c @@ -167,5 +167,6 @@ blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm) } FreeAccessStrategy(bas); bloomUsage.matches += ntids; + return ntids; } diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c index d8fff4f057..1ba7afc607 100644 --- a/contrib/bloom/blutils.c +++ b/contrib/bloom/blutils.c @@ -38,19 +38,23 @@ PG_FUNCTION_INFO_V1(blhandler); BloomUsage bloomUsage; static void -bloomUsageAdd(CustomResourceUsage* dst, CustomResourceUsage const* add) +bloomUsageAdd(CustomResourceUsage *dst, + CustomResourceUsage const *add) { - ((BloomUsage*)dst)->matches += ((BloomUsage*)add)->matches; + ((BloomUsage*) dst)->matches += ((BloomUsage*) add)->matches; } static void -bloomUsageAccum(CustomResourceUsage* acc, CustomResourceUsage const* end, CustomResourceUsage const* start) +bloomUsageAccum(CustomResourceUsage* acc, + CustomResourceUsage const *end, + CustomResourceUsage const *start) { - ((BloomUsage*)acc)->matches += ((BloomUsage*)end)->matches - ((BloomUsage*)start)->matches;; + ((BloomUsage*) acc)->matches += + ((BloomUsage*) end)->matches - ((BloomUsage*) start)->matches; } static void -bloomUsageShow(ExplainState* es, CustomResourceUsage const* usage, bool planning) +bloomUsageShow(ExplainState *es, CustomResourceUsage const *usage, bool planning) { if (es->format == EXPLAIN_FORMAT_TEXT) { @@ -60,18 +64,20 @@ bloomUsageShow(ExplainState* es, CustomResourceUsage const* usage, bool planning appendStringInfoString(es->str, "Planning:\n"); es->indent++; } + ExplainIndentText(es); appendStringInfoString(es->str, "Bloom:"); appendStringInfo(es->str, " matches=%lld", - (long long) ((BloomUsage*)usage)->matches); + (long long) ((BloomUsage*) usage)->matches); appendStringInfoChar(es->str, '\n'); + if (planning) es->indent--; } else { ExplainPropertyInteger("Bloom Matches", NULL, - ((BloomUsage*)usage)->matches, es); + ((BloomUsage*) usage)->matches, es); } } @@ -128,6 +134,7 @@ _PG_init(void) bl_relopt_tab[i + 1].opttype = RELOPT_TYPE_INT; bl_relopt_tab[i + 1].offset = offsetof(BloomOptions, bitSize[0]) + sizeof(int) * i; } + RegisterCustomInsrumentation(&bloomInstr); } diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index a4ab0d6ba0..e9dc1190af 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -1635,7 +1635,6 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request) mul_size(pgCustUsageSize, pcxt->nworkers)); shm_toc_insert(pcxt->toc, PARALLEL_KEY_CUST_USAGE, custusage); - /* Launch workers, saving status for leader/caller */ LaunchParallelWorkers(pcxt); btleader->pcxt = pcxt; @@ -1687,7 +1686,9 @@ _bt_end_parallel(BTLeader *btleader) * or we might get incomplete data.) */ for (i = 0; i < btleader->pcxt->nworkers_launched; i++) - InstrAccumParallelQuery(&btleader->bufferusage[i], &btleader->walusage[i], btleader->custusage + pgCustUsageSize*i); + InstrAccumParallelQuery(&btleader->bufferusage[i], + &btleader->walusage[i], + btleader->custusage + pgCustUsageSize * i); /* Free last reference to MVCC snapshot, if one was used */ if (IsMVCCSnapshot(btleader->snapshot)) @@ -1906,7 +1907,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc) custusage = shm_toc_lookup(toc, PARALLEL_KEY_CUST_USAGE, false); InstrEndParallelQuery(&bufferusage[ParallelWorkerNumber], &walusage[ParallelWorkerNumber], - custusage + ParallelWorkerNumber*pgCustUsageSize); + custusage + ParallelWorkerNumber * pgCustUsageSize); #ifdef BTREE_BUILD_STATS if (log_btree_build_stats) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index d3dc19f3ce..a5dc8451f5 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -226,9 +226,11 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, else { bool found = false; + foreach (c, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(c); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(c); + if (strcmp(opt->defname, ci->name) == 0) { ci->selected = true; @@ -339,7 +341,7 @@ ExplainState * NewExplainState(void) { ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState)); - ListCell* lc; + ListCell *lc; /* Set default options (most fields can be left as zeroes). */ es->costs = true; @@ -349,7 +351,8 @@ NewExplainState(void) /* Reset custom instrumentations selection flag */ foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + ci->selected = false; } return es; @@ -3598,15 +3601,17 @@ explain_get_index_name(Oid indexId) * Show select custom usage details */ static void -show_custom_usage(ExplainState *es, const char* usage, bool planning) +show_custom_usage(ExplainState *es, const char *usage, bool planning) { - ListCell* lc; + ListCell *lc; foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + if (ci->selected) ci->show(es, usage, planning); + usage += ci->size; } } diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index 299782b2f7..5afb31d145 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -411,7 +411,7 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes, mul_size(sizeof(WalUsage), pcxt->nworkers)); shm_toc_insert(pcxt->toc, PARALLEL_VACUUM_KEY_WAL_USAGE, wal_usage); pvs->wal_usage = wal_usage; - custom_usage = shm_toc_allocate(pcxt->toc, + custom_usage = shm_toc_allocate(pcxt->toc, mul_size(pgCustUsageSize, pcxt->nworkers)); shm_toc_insert(pcxt->toc, PARALLEL_VACUUM_KEY_CUSTOM_USAGE, custom_usage); pvs->custom_usage = custom_usage; @@ -718,7 +718,8 @@ parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scan WaitForParallelWorkersToFinish(pvs->pcxt); for (int i = 0; i < pvs->pcxt->nworkers_launched; i++) - InstrAccumParallelQuery(&pvs->buffer_usage[i], &pvs->wal_usage[i], pvs->custom_usage + pgCustUsageSize*i); + InstrAccumParallelQuery(&pvs->buffer_usage[i], &pvs->wal_usage[i], + pvs->custom_usage + pgCustUsageSize * i); } /* diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index 39d9754a0f..cba8fe7795 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -1178,7 +1178,8 @@ ExecParallelFinish(ParallelExecutorInfo *pei) * finish, or we might get incomplete data.) */ for (i = 0; i < nworkers; i++) - InstrAccumParallelQuery(&pei->buffer_usage[i], &pei->wal_usage[i], pei->custom_usage + pgCustUsageSize*i); + InstrAccumParallelQuery(&pei->buffer_usage[i], &pei->wal_usage[i], + pei->custom_usage + pgCustUsageSize * i); pei->finished = true; } @@ -1411,7 +1412,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc) FixedParallelExecutorState *fpes; BufferUsage *buffer_usage; WalUsage *wal_usage; - char *custom_usage; + char *custom_usage; DestReceiver *receiver; QueryDesc *queryDesc; SharedExecutorInstrumentation *instrumentation; diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c index ca3e7eff74..d37b783616 100644 --- a/src/backend/executor/instrument.c +++ b/src/backend/executor/instrument.c @@ -23,33 +23,36 @@ static BufferUsage save_pgBufferUsage; WalUsage pgWalUsage; static WalUsage save_pgWalUsage; -List* pgCustInstr; /* description of custom instriumentations */ +List *pgCustInstr; /* description of custom instriumentations */ Size pgCustUsageSize; static CustomInstrumentationData save_pgCustUsage; /* saved custom instrumentation state */ - static void BufferUsageAdd(BufferUsage *dst, const BufferUsage *add); static void WalUsageAdd(WalUsage *dst, WalUsage *add); void -RegisterCustomInsrumentation(CustomInstrumentation* inst) +RegisterCustomInsrumentation(CustomInstrumentation *inst) { MemoryContext oldcontext = MemoryContextSwitchTo(TopMemoryContext); + pgCustInstr = lappend(pgCustInstr, inst); pgCustUsageSize += inst->size; MemoryContextSwitchTo(oldcontext); + if (pgCustUsageSize > MAX_CUSTOM_INSTR_SIZE) - elog(ERROR, "Total size of custom instrumentations exceed limit %d", MAX_CUSTOM_INSTR_SIZE); + elog(ERROR, "Total size of custom instrumentations exceed limit %d", + MAX_CUSTOM_INSTR_SIZE); } void -GetCustomInstrumentationState(char* dst) +GetCustomInstrumentationState(char *dst) { - ListCell* lc; + ListCell *lc; foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + memcpy(dst, ci->usage, ci->size); dst += ci->size; } @@ -58,16 +61,18 @@ GetCustomInstrumentationState(char* dst) void AccumulateCustomInstrumentationState(char* dst, char const* before) { - ListCell* lc; + ListCell *lc; foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + if (ci->selected) { memset(dst, 0, ci->size); ci->accum(dst, ci->usage, before); } + dst += ci->size; before += ci->size; } @@ -96,6 +101,7 @@ InstrAlloc(int n, int instrument_options, bool async_mode) instr[i].async_mode = async_mode; } } + return instr; } @@ -113,8 +119,9 @@ InstrInit(Instrumentation *instr, int instrument_options) void InstrStartNode(Instrumentation *instr) { - ListCell *lc; - char* cust_start = instr->cust_usage_start.data; + ListCell *lc; + char *cust_start = instr->cust_usage_start.data; + if (instr->need_timer && !INSTR_TIME_SET_CURRENT_LAZY(instr->starttime)) elog(ERROR, "InstrStartNode called twice in a row"); @@ -128,7 +135,8 @@ InstrStartNode(Instrumentation *instr) foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + memcpy(cust_start, ci->usage, ci->size); cust_start += ci->size; } @@ -140,9 +148,9 @@ InstrStopNode(Instrumentation *instr, double nTuples) { double save_tuplecount = instr->tuplecount; instr_time endtime; - ListCell *lc; - char *cust_start = instr->cust_usage_start.data; - char *cust_usage = instr->cust_usage.data; + ListCell *lc; + char *cust_start = instr->cust_usage_start.data; + char *cust_usage = instr->cust_usage.data; /* count the returned tuples */ instr->tuplecount += nTuples; @@ -170,13 +178,14 @@ InstrStopNode(Instrumentation *instr, double nTuples) foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + ci->accum(cust_usage, ci->usage, cust_start); cust_start += ci->size; cust_usage += ci->size; } - /* Is this the first tuple of this cycle? */ + /* Is this the first tuple of this cycle? */ if (!instr->running) { instr->running = true; @@ -234,9 +243,9 @@ InstrEndLoop(Instrumentation *instr) void InstrAggNode(Instrumentation *dst, Instrumentation *add) { - ListCell *lc; - char *cust_dst = dst->cust_usage.data; - char *cust_add = add->cust_usage.data; + ListCell *lc; + char *cust_dst = dst->cust_usage.data; + char *cust_add = add->cust_usage.data; if (!dst->running && add->running) { @@ -266,7 +275,8 @@ InstrAggNode(Instrumentation *dst, Instrumentation *add) foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + ci->add(cust_dst, cust_add); cust_dst += ci->size; cust_add += ci->size; @@ -277,15 +287,16 @@ InstrAggNode(Instrumentation *dst, Instrumentation *add) void InstrStartParallelQuery(void) { - ListCell* lc; - char* cust_dst = save_pgCustUsage.data; + ListCell *lc; + char *cust_dst = save_pgCustUsage.data; save_pgBufferUsage = pgBufferUsage; save_pgWalUsage = pgWalUsage; foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + memcpy(cust_dst, ci->usage, ci->size); cust_dst += ci->size; } @@ -295,8 +306,8 @@ InstrStartParallelQuery(void) void InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage, char* cust_usage) { - ListCell *lc; - char* cust_save = save_pgCustUsage.data; + ListCell *lc; + char *cust_save = save_pgCustUsage.data; memset(bufusage, 0, sizeof(BufferUsage)); BufferUsageAccumDiff(bufusage, &pgBufferUsage, &save_pgBufferUsage); @@ -305,7 +316,8 @@ InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage, char* cust_usag foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + ci->accum(cust_usage, ci->usage, cust_save); cust_usage += ci->size; cust_save += ci->size; @@ -316,13 +328,15 @@ InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage, char* cust_usag void InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage, char* cust_usage) { - ListCell *lc; + ListCell *lc; + BufferUsageAdd(&pgBufferUsage, bufusage); WalUsageAdd(&pgWalUsage, walusage); foreach (lc, pgCustInstr) { - CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + CustomInstrumentation *ci = (CustomInstrumentation*) lfirst(lc); + ci->add(ci->usage, cust_usage); cust_usage += ci->size; } -- 2.43.0 [text/x-patch] v20231129-0001-custom-explain-options.patch (32.0K, ../../CAFj8pRDXQX9F+wDVPuBdM2UGDvxfLY5Pf1=dtk2x2=7GUBPsqA@mail.gmail.com/4-v20231129-0001-custom-explain-options.patch) download | inline diff: From 652244e518cc0a47c43955d335e3f9372d7925be Mon Sep 17 00:00:00 2001 From: "[email protected]" <[email protected]> Date: Sat, 25 Nov 2023 08:21:24 +0100 Subject: [PATCH 1/2] custom explain options --- contrib/bloom/bloom.h | 7 ++ contrib/bloom/blscan.c | 2 +- contrib/bloom/blutils.c | 51 ++++++++++++ src/backend/access/nbtree/nbtsort.c | 18 +++- src/backend/commands/explain.c | 79 ++++++++++++++++-- src/backend/commands/prepare.c | 10 ++- src/backend/commands/vacuumparallel.c | 19 ++++- src/backend/executor/execParallel.c | 21 ++++- src/backend/executor/instrument.c | 115 +++++++++++++++++++++++++- src/include/commands/explain.h | 5 +- src/include/executor/execParallel.h | 1 + src/include/executor/instrument.h | 43 +++++++++- 12 files changed, 349 insertions(+), 22 deletions(-) diff --git a/contrib/bloom/bloom.h b/contrib/bloom/bloom.h index 330811ec60..af23ffe821 100644 --- a/contrib/bloom/bloom.h +++ b/contrib/bloom/bloom.h @@ -174,6 +174,13 @@ typedef struct BloomScanOpaqueData typedef BloomScanOpaqueData *BloomScanOpaque; +typedef struct +{ + uint64 matches; +} BloomUsage; + +extern BloomUsage bloomUsage; + /* blutils.c */ extern void initBloomState(BloomState *state, Relation index); extern void BloomFillMetapage(Relation index, Page metaPage); diff --git a/contrib/bloom/blscan.c b/contrib/bloom/blscan.c index 61d1f66b38..8890951943 100644 --- a/contrib/bloom/blscan.c +++ b/contrib/bloom/blscan.c @@ -166,6 +166,6 @@ blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm) CHECK_FOR_INTERRUPTS(); } FreeAccessStrategy(bas); - + bloomUsage.matches += ntids; return ntids; } diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c index 4830cb3fee..d8fff4f057 100644 --- a/contrib/bloom/blutils.c +++ b/contrib/bloom/blutils.c @@ -18,6 +18,7 @@ #include "access/reloptions.h" #include "bloom.h" #include "catalog/index.h" +#include "commands/explain.h" #include "commands/vacuum.h" #include "miscadmin.h" #include "storage/bufmgr.h" @@ -34,6 +35,55 @@ PG_FUNCTION_INFO_V1(blhandler); +BloomUsage bloomUsage; + +static void +bloomUsageAdd(CustomResourceUsage* dst, CustomResourceUsage const* add) +{ + ((BloomUsage*)dst)->matches += ((BloomUsage*)add)->matches; +} + +static void +bloomUsageAccum(CustomResourceUsage* acc, CustomResourceUsage const* end, CustomResourceUsage const* start) +{ + ((BloomUsage*)acc)->matches += ((BloomUsage*)end)->matches - ((BloomUsage*)start)->matches;; +} + +static void +bloomUsageShow(ExplainState* es, CustomResourceUsage const* usage, bool planning) +{ + if (es->format == EXPLAIN_FORMAT_TEXT) + { + if (planning) + { + ExplainIndentText(es); + appendStringInfoString(es->str, "Planning:\n"); + es->indent++; + } + ExplainIndentText(es); + appendStringInfoString(es->str, "Bloom:"); + appendStringInfo(es->str, " matches=%lld", + (long long) ((BloomUsage*)usage)->matches); + appendStringInfoChar(es->str, '\n'); + if (planning) + es->indent--; + } + else + { + ExplainPropertyInteger("Bloom Matches", NULL, + ((BloomUsage*)usage)->matches, es); + } +} + +static CustomInstrumentation bloomInstr = { + "bloom", + sizeof(BloomUsage), + &bloomUsage, + bloomUsageAdd, + bloomUsageAccum, + bloomUsageShow +}; + /* Kind of relation options for bloom index */ static relopt_kind bl_relopt_kind; @@ -78,6 +128,7 @@ _PG_init(void) bl_relopt_tab[i + 1].opttype = RELOPT_TYPE_INT; bl_relopt_tab[i + 1].offset = offsetof(BloomOptions, bitSize[0]) + sizeof(int) * i; } + RegisterCustomInsrumentation(&bloomInstr); } /* diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index c2665fce41..a4ab0d6ba0 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -71,6 +71,7 @@ #define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xA000000000000004) #define PARALLEL_KEY_WAL_USAGE UINT64CONST(0xA000000000000005) #define PARALLEL_KEY_BUFFER_USAGE UINT64CONST(0xA000000000000006) +#define PARALLEL_KEY_CUST_USAGE UINT64CONST(0xA000000000000007) /* * DISABLE_LEADER_PARTICIPATION disables the leader's participation in @@ -197,6 +198,7 @@ typedef struct BTLeader Snapshot snapshot; WalUsage *walusage; BufferUsage *bufferusage; + char *custusage; } BTLeader; /* @@ -1467,6 +1469,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request) BTLeader *btleader = (BTLeader *) palloc0(sizeof(BTLeader)); WalUsage *walusage; BufferUsage *bufferusage; + char *custusage; bool leaderparticipates = true; int querylen; @@ -1532,6 +1535,9 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request) shm_toc_estimate_chunk(&pcxt->estimator, mul_size(sizeof(BufferUsage), pcxt->nworkers)); shm_toc_estimate_keys(&pcxt->estimator, 1); + shm_toc_estimate_chunk(&pcxt->estimator, + mul_size(pgCustUsageSize, pcxt->nworkers)); + shm_toc_estimate_keys(&pcxt->estimator, 1); /* Finally, estimate PARALLEL_KEY_QUERY_TEXT space */ if (debug_query_string) @@ -1625,6 +1631,10 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request) bufferusage = shm_toc_allocate(pcxt->toc, mul_size(sizeof(BufferUsage), pcxt->nworkers)); shm_toc_insert(pcxt->toc, PARALLEL_KEY_BUFFER_USAGE, bufferusage); + custusage = shm_toc_allocate(pcxt->toc, + mul_size(pgCustUsageSize, pcxt->nworkers)); + shm_toc_insert(pcxt->toc, PARALLEL_KEY_CUST_USAGE, custusage); + /* Launch workers, saving status for leader/caller */ LaunchParallelWorkers(pcxt); @@ -1638,6 +1648,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request) btleader->snapshot = snapshot; btleader->walusage = walusage; btleader->bufferusage = bufferusage; + btleader->custusage = custusage; /* If no workers were successfully launched, back out (do serial build) */ if (pcxt->nworkers_launched == 0) @@ -1676,7 +1687,7 @@ _bt_end_parallel(BTLeader *btleader) * or we might get incomplete data.) */ for (i = 0; i < btleader->pcxt->nworkers_launched; i++) - InstrAccumParallelQuery(&btleader->bufferusage[i], &btleader->walusage[i]); + InstrAccumParallelQuery(&btleader->bufferusage[i], &btleader->walusage[i], btleader->custusage + pgCustUsageSize*i); /* Free last reference to MVCC snapshot, if one was used */ if (IsMVCCSnapshot(btleader->snapshot)) @@ -1811,6 +1822,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc) LOCKMODE indexLockmode; WalUsage *walusage; BufferUsage *bufferusage; + char *custusage; int sortmem; #ifdef BTREE_BUILD_STATS @@ -1891,8 +1903,10 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc) /* Report WAL/buffer usage during parallel execution */ bufferusage = shm_toc_lookup(toc, PARALLEL_KEY_BUFFER_USAGE, false); walusage = shm_toc_lookup(toc, PARALLEL_KEY_WAL_USAGE, false); + custusage = shm_toc_lookup(toc, PARALLEL_KEY_CUST_USAGE, false); InstrEndParallelQuery(&bufferusage[ParallelWorkerNumber], - &walusage[ParallelWorkerNumber]); + &walusage[ParallelWorkerNumber], + custusage + ParallelWorkerNumber*pgCustUsageSize); #ifdef BTREE_BUILD_STATS if (log_btree_build_stats) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index f1d71bc54e..d3dc19f3ce 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -119,6 +119,8 @@ static void show_instrumentation_count(const char *qlabel, int which, static void show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es); static void show_eval_params(Bitmapset *bms_params, ExplainState *es); static const char *explain_get_index_name(Oid indexId); +static void show_custom_usage(ExplainState *es, const char* usage, + bool planning); static void show_buffer_usage(ExplainState *es, const BufferUsage *usage, bool planning); static void show_wal_usage(ExplainState *es, const WalUsage *usage); @@ -149,7 +151,6 @@ static void ExplainRestoreGroup(ExplainState *es, int depth, int *state_save); static void ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es); static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es); -static void ExplainIndentText(ExplainState *es); static void ExplainJSONLineEnding(ExplainState *es); static void ExplainYAMLLineStarting(ExplainState *es); static void escape_yaml(StringInfo buf, const char *str); @@ -170,6 +171,7 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, Query *query; List *rewritten; ListCell *lc; + ListCell *c; bool timing_set = false; bool summary_set = false; @@ -222,11 +224,28 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, parser_errposition(pstate, opt->location))); } else - ereport(ERROR, + { + bool found = false; + foreach (c, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(c); + if (strcmp(opt->defname, ci->name) == 0) + { + ci->selected = true; + es->custom = true; + found = true; + break; + } + } + if (!found) + { + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("unrecognized EXPLAIN option \"%s\"", opt->defname), parser_errposition(pstate, opt->location))); + } + } } /* check that WAL is used with EXPLAIN ANALYZE */ @@ -320,12 +339,19 @@ ExplainState * NewExplainState(void) { ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState)); + ListCell* lc; /* Set default options (most fields can be left as zeroes). */ es->costs = true; /* Prepare output buffer. */ es->str = makeStringInfo(); + /* Reset custom instrumentations selection flag */ + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + ci->selected = false; + } return es; } @@ -397,9 +423,14 @@ ExplainOneQuery(Query *query, int cursorOptions, planduration; BufferUsage bufusage_start, bufusage; + CustomInstrumentationData custusage_start, custusage; if (es->buffers) bufusage_start = pgBufferUsage; + + if (es->custom) + GetCustomInstrumentationState(custusage_start.data); + INSTR_TIME_SET_CURRENT(planstart); /* plan the query */ @@ -415,9 +446,14 @@ ExplainOneQuery(Query *query, int cursorOptions, BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start); } + if (es->custom) + AccumulateCustomInstrumentationState(custusage.data, custusage_start.data); + /* run it (if needed) and produce output */ ExplainOnePlan(plan, into, es, queryString, params, queryEnv, - &planduration, (es->buffers ? &bufusage : NULL)); + &planduration, + (es->buffers ? &bufusage : NULL), + (es->custom ? &custusage : NULL)); } } @@ -527,7 +563,8 @@ void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, - const BufferUsage *bufusage) + const BufferUsage *bufusage, + const CustomInstrumentationData *custusage) { DestReceiver *dest; QueryDesc *queryDesc; @@ -623,6 +660,13 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, ExplainCloseGroup("Planning", "Planning", true, es); } + if (custusage) + { + ExplainOpenGroup("Planning", "Planning", true, es); + show_custom_usage(es, custusage->data, true); + ExplainCloseGroup("Planning", "Planning", true, es); + } + if (es->summary && planduration) { double plantime = INSTR_TIME_GET_DOUBLE(*planduration); @@ -2110,8 +2154,12 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->wal && planstate->instrument) show_wal_usage(es, &planstate->instrument->walusage); + /* Show custom instrumentation */ + if (es->custom && planstate->instrument) + show_custom_usage(es, planstate->instrument->cust_usage.data, false); + /* Prepare per-worker buffer/WAL usage */ - if (es->workers_state && (es->buffers || es->wal) && es->verbose) + if (es->workers_state && (es->buffers || es->wal || es->custom) && es->verbose) { WorkerInstrumentation *w = planstate->worker_instrument; @@ -2128,6 +2176,8 @@ ExplainNode(PlanState *planstate, List *ancestors, show_buffer_usage(es, &instrument->bufusage, false); if (es->wal) show_wal_usage(es, &instrument->walusage); + if (es->custom) + show_custom_usage(es, instrument->cust_usage.data, false); ExplainCloseWorker(n, es); } } @@ -3544,6 +3594,23 @@ explain_get_index_name(Oid indexId) return result; } +/* + * Show select custom usage details + */ +static void +show_custom_usage(ExplainState *es, const char* usage, bool planning) +{ + ListCell* lc; + + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + if (ci->selected) + ci->show(es, usage, planning); + usage += ci->size; + } +} + /* * Show buffer usage details. */ @@ -5017,7 +5084,7 @@ ExplainXMLTag(const char *tagname, int flags, ExplainState *es) * data for a parallel worker there might already be data on the current line * (cf. ExplainOpenWorker); in that case, don't indent any more. */ -static void +void ExplainIndentText(ExplainState *es) { Assert(es->format == EXPLAIN_FORMAT_TEXT); diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 18f70319fc..7999980699 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -583,9 +583,13 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, instr_time planduration; BufferUsage bufusage_start, bufusage; + CustomInstrumentationData custusage_start, custusage; if (es->buffers) bufusage_start = pgBufferUsage; + if (es->custom) + GetCustomInstrumentationState(custusage_start.data); + INSTR_TIME_SET_CURRENT(planstart); /* Look it up in the hash table */ @@ -630,6 +634,8 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, memset(&bufusage, 0, sizeof(BufferUsage)); BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start); } + if (es->custom) + AccumulateCustomInstrumentationState(custusage.data, custusage_start.data); plan_list = cplan->stmt_list; @@ -640,7 +646,9 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, if (pstmt->commandType != CMD_UTILITY) ExplainOnePlan(pstmt, into, es, query_string, paramLI, queryEnv, - &planduration, (es->buffers ? &bufusage : NULL)); + &planduration, + (es->buffers ? &bufusage : NULL), + (es->custom ? &custusage : NULL)); else ExplainOneUtility(pstmt->utilityStmt, into, es, query_string, paramLI, queryEnv); diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index 176c555d63..299782b2f7 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -50,6 +50,7 @@ #define PARALLEL_VACUUM_KEY_BUFFER_USAGE 4 #define PARALLEL_VACUUM_KEY_WAL_USAGE 5 #define PARALLEL_VACUUM_KEY_INDEX_STATS 6 +#define PARALLEL_VACUUM_KEY_CUSTOM_USAGE 7 /* * Shared information among parallel workers. So this is allocated in the DSM @@ -184,6 +185,9 @@ struct ParallelVacuumState /* Points to WAL usage area in DSM */ WalUsage *wal_usage; + /* Points to custom usage area in DSM */ + char *custom_usage; + /* * False if the index is totally unsuitable target for all parallel * processing. For example, the index could be < @@ -242,6 +246,7 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes, PVIndStats *indstats; BufferUsage *buffer_usage; WalUsage *wal_usage; + char *custom_usage; bool *will_parallel_vacuum; Size est_indstats_len; Size est_shared_len; @@ -313,6 +318,9 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes, shm_toc_estimate_chunk(&pcxt->estimator, mul_size(sizeof(WalUsage), pcxt->nworkers)); shm_toc_estimate_keys(&pcxt->estimator, 1); + shm_toc_estimate_chunk(&pcxt->estimator, + mul_size(pgCustUsageSize, pcxt->nworkers)); + shm_toc_estimate_keys(&pcxt->estimator, 1); /* Finally, estimate PARALLEL_VACUUM_KEY_QUERY_TEXT space */ if (debug_query_string) @@ -403,6 +411,10 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes, mul_size(sizeof(WalUsage), pcxt->nworkers)); shm_toc_insert(pcxt->toc, PARALLEL_VACUUM_KEY_WAL_USAGE, wal_usage); pvs->wal_usage = wal_usage; + custom_usage = shm_toc_allocate(pcxt->toc, + mul_size(pgCustUsageSize, pcxt->nworkers)); + shm_toc_insert(pcxt->toc, PARALLEL_VACUUM_KEY_CUSTOM_USAGE, custom_usage); + pvs->custom_usage = custom_usage; /* Store query string for workers */ if (debug_query_string) @@ -706,7 +718,7 @@ parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scan WaitForParallelWorkersToFinish(pvs->pcxt); for (int i = 0; i < pvs->pcxt->nworkers_launched; i++) - InstrAccumParallelQuery(&pvs->buffer_usage[i], &pvs->wal_usage[i]); + InstrAccumParallelQuery(&pvs->buffer_usage[i], &pvs->wal_usage[i], pvs->custom_usage + pgCustUsageSize*i); } /* @@ -964,6 +976,7 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) VacDeadItems *dead_items; BufferUsage *buffer_usage; WalUsage *wal_usage; + char *custom_usage; int nindexes; char *sharedquery; ErrorContextCallback errcallback; @@ -1053,8 +1066,10 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) /* Report buffer/WAL usage during parallel execution */ buffer_usage = shm_toc_lookup(toc, PARALLEL_VACUUM_KEY_BUFFER_USAGE, false); wal_usage = shm_toc_lookup(toc, PARALLEL_VACUUM_KEY_WAL_USAGE, false); + custom_usage = shm_toc_lookup(toc, PARALLEL_VACUUM_KEY_CUSTOM_USAGE, false); InstrEndParallelQuery(&buffer_usage[ParallelWorkerNumber], - &wal_usage[ParallelWorkerNumber]); + &wal_usage[ParallelWorkerNumber], + custom_usage + pgCustUsageSize*ParallelWorkerNumber); /* Pop the error context stack */ error_context_stack = errcallback.previous; diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index cc2b8ccab7..39d9754a0f 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -66,6 +66,7 @@ #define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xE000000000000008) #define PARALLEL_KEY_JIT_INSTRUMENTATION UINT64CONST(0xE000000000000009) #define PARALLEL_KEY_WAL_USAGE UINT64CONST(0xE00000000000000A) +#define PARALLEL_KEY_CUSTOM_USAGE UINT64CONST(0xE00000000000000B) #define PARALLEL_TUPLE_QUEUE_SIZE 65536 @@ -600,6 +601,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, char *paramlistinfo_space; BufferUsage *bufusage_space; WalUsage *walusage_space; + char *customusage_space; SharedExecutorInstrumentation *instrumentation = NULL; SharedJitInstrumentation *jit_instrumentation = NULL; int pstmt_len; @@ -680,6 +682,13 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, mul_size(sizeof(WalUsage), pcxt->nworkers)); shm_toc_estimate_keys(&pcxt->estimator, 1); + /* + * Same thing for CustomUsage. + */ + shm_toc_estimate_chunk(&pcxt->estimator, + mul_size(pgCustUsageSize, pcxt->nworkers)); + shm_toc_estimate_keys(&pcxt->estimator, 1); + /* Estimate space for tuple queues. */ shm_toc_estimate_chunk(&pcxt->estimator, mul_size(PARALLEL_TUPLE_QUEUE_SIZE, pcxt->nworkers)); @@ -768,6 +777,11 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, shm_toc_insert(pcxt->toc, PARALLEL_KEY_WAL_USAGE, walusage_space); pei->wal_usage = walusage_space; + customusage_space = shm_toc_allocate(pcxt->toc, + mul_size(pgCustUsageSize, pcxt->nworkers)); + shm_toc_insert(pcxt->toc, PARALLEL_KEY_CUSTOM_USAGE, customusage_space); + pei->custom_usage = customusage_space; + /* Set up the tuple queues that the workers will write into. */ pei->tqueue = ExecParallelSetupTupleQueues(pcxt, false); @@ -1164,7 +1178,7 @@ ExecParallelFinish(ParallelExecutorInfo *pei) * finish, or we might get incomplete data.) */ for (i = 0; i < nworkers; i++) - InstrAccumParallelQuery(&pei->buffer_usage[i], &pei->wal_usage[i]); + InstrAccumParallelQuery(&pei->buffer_usage[i], &pei->wal_usage[i], pei->custom_usage + pgCustUsageSize*i); pei->finished = true; } @@ -1397,6 +1411,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc) FixedParallelExecutorState *fpes; BufferUsage *buffer_usage; WalUsage *wal_usage; + char *custom_usage; DestReceiver *receiver; QueryDesc *queryDesc; SharedExecutorInstrumentation *instrumentation; @@ -1472,8 +1487,10 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc) /* Report buffer/WAL usage during parallel execution. */ buffer_usage = shm_toc_lookup(toc, PARALLEL_KEY_BUFFER_USAGE, false); wal_usage = shm_toc_lookup(toc, PARALLEL_KEY_WAL_USAGE, false); + custom_usage = shm_toc_lookup(toc, PARALLEL_KEY_CUSTOM_USAGE, false); InstrEndParallelQuery(&buffer_usage[ParallelWorkerNumber], - &wal_usage[ParallelWorkerNumber]); + &wal_usage[ParallelWorkerNumber], + custom_usage + ParallelWorkerNumber*pgCustUsageSize); /* Report instrumentation data if any instrumentation options are set. */ if (instrumentation != NULL) diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c index c383f34c06..ca3e7eff74 100644 --- a/src/backend/executor/instrument.c +++ b/src/backend/executor/instrument.c @@ -16,15 +16,62 @@ #include <unistd.h> #include "executor/instrument.h" +#include "utils/memutils.h" BufferUsage pgBufferUsage; static BufferUsage save_pgBufferUsage; WalUsage pgWalUsage; static WalUsage save_pgWalUsage; +List* pgCustInstr; /* description of custom instriumentations */ +Size pgCustUsageSize; +static CustomInstrumentationData save_pgCustUsage; /* saved custom instrumentation state */ + + static void BufferUsageAdd(BufferUsage *dst, const BufferUsage *add); static void WalUsageAdd(WalUsage *dst, WalUsage *add); +void +RegisterCustomInsrumentation(CustomInstrumentation* inst) +{ + MemoryContext oldcontext = MemoryContextSwitchTo(TopMemoryContext); + pgCustInstr = lappend(pgCustInstr, inst); + pgCustUsageSize += inst->size; + MemoryContextSwitchTo(oldcontext); + if (pgCustUsageSize > MAX_CUSTOM_INSTR_SIZE) + elog(ERROR, "Total size of custom instrumentations exceed limit %d", MAX_CUSTOM_INSTR_SIZE); +} + +void +GetCustomInstrumentationState(char* dst) +{ + ListCell* lc; + + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + memcpy(dst, ci->usage, ci->size); + dst += ci->size; + } +} + +void +AccumulateCustomInstrumentationState(char* dst, char const* before) +{ + ListCell* lc; + + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + if (ci->selected) + { + memset(dst, 0, ci->size); + ci->accum(dst, ci->usage, before); + } + dst += ci->size; + before += ci->size; + } +} /* Allocate new instrumentation structure(s) */ Instrumentation * @@ -49,7 +96,6 @@ InstrAlloc(int n, int instrument_options, bool async_mode) instr[i].async_mode = async_mode; } } - return instr; } @@ -67,6 +113,8 @@ InstrInit(Instrumentation *instr, int instrument_options) void InstrStartNode(Instrumentation *instr) { + ListCell *lc; + char* cust_start = instr->cust_usage_start.data; if (instr->need_timer && !INSTR_TIME_SET_CURRENT_LAZY(instr->starttime)) elog(ERROR, "InstrStartNode called twice in a row"); @@ -77,6 +125,13 @@ InstrStartNode(Instrumentation *instr) if (instr->need_walusage) instr->walusage_start = pgWalUsage; + + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + memcpy(cust_start, ci->usage, ci->size); + cust_start += ci->size; + } } /* Exit from a plan node */ @@ -85,6 +140,9 @@ InstrStopNode(Instrumentation *instr, double nTuples) { double save_tuplecount = instr->tuplecount; instr_time endtime; + ListCell *lc; + char *cust_start = instr->cust_usage_start.data; + char *cust_usage = instr->cust_usage.data; /* count the returned tuples */ instr->tuplecount += nTuples; @@ -110,7 +168,15 @@ InstrStopNode(Instrumentation *instr, double nTuples) WalUsageAccumDiff(&instr->walusage, &pgWalUsage, &instr->walusage_start); - /* Is this the first tuple of this cycle? */ + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + ci->accum(cust_usage, ci->usage, cust_start); + cust_start += ci->size; + cust_usage += ci->size; + } + + /* Is this the first tuple of this cycle? */ if (!instr->running) { instr->running = true; @@ -168,6 +234,10 @@ InstrEndLoop(Instrumentation *instr) void InstrAggNode(Instrumentation *dst, Instrumentation *add) { + ListCell *lc; + char *cust_dst = dst->cust_usage.data; + char *cust_add = add->cust_usage.data; + if (!dst->running && add->running) { dst->running = true; @@ -193,32 +263,69 @@ InstrAggNode(Instrumentation *dst, Instrumentation *add) if (dst->need_walusage) WalUsageAdd(&dst->walusage, &add->walusage); + + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + ci->add(cust_dst, cust_add); + cust_dst += ci->size; + cust_add += ci->size; + } } /* note current values during parallel executor startup */ void InstrStartParallelQuery(void) { + ListCell* lc; + char* cust_dst = save_pgCustUsage.data; + save_pgBufferUsage = pgBufferUsage; save_pgWalUsage = pgWalUsage; + + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + memcpy(cust_dst, ci->usage, ci->size); + cust_dst += ci->size; + } } /* report usage after parallel executor shutdown */ void -InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage) +InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage, char* cust_usage) { + ListCell *lc; + char* cust_save = save_pgCustUsage.data; + memset(bufusage, 0, sizeof(BufferUsage)); BufferUsageAccumDiff(bufusage, &pgBufferUsage, &save_pgBufferUsage); memset(walusage, 0, sizeof(WalUsage)); WalUsageAccumDiff(walusage, &pgWalUsage, &save_pgWalUsage); + + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + ci->accum(cust_usage, ci->usage, cust_save); + cust_usage += ci->size; + cust_save += ci->size; + } } /* accumulate work done by workers in leader's stats */ void -InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage) +InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage, char* cust_usage) { + ListCell *lc; BufferUsageAdd(&pgBufferUsage, bufusage); WalUsageAdd(&pgWalUsage, walusage); + + foreach (lc, pgCustInstr) + { + CustomInstrumentation *ci = (CustomInstrumentation*)lfirst(lc); + ci->add(ci->usage, cust_usage); + cust_usage += ci->size; + } } /* dst += add */ diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h index f9525fb572..9c25a85e92 100644 --- a/src/include/commands/explain.h +++ b/src/include/commands/explain.h @@ -41,6 +41,7 @@ typedef struct ExplainState bool verbose; /* be verbose */ bool analyze; /* print actual times */ bool costs; /* print estimated costs */ + bool custom; /* print custom usage */ bool buffers; /* print buffer usage */ bool wal; /* print WAL usage */ bool timing; /* print detailed node timing */ @@ -92,7 +93,8 @@ extern void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, - const BufferUsage *bufusage); + const BufferUsage *bufusage, + const CustomInstrumentationData *custusage); extern void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc); extern void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc); @@ -125,5 +127,6 @@ extern void ExplainOpenGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es); extern void ExplainCloseGroup(const char *objtype, const char *labelname, bool labeled, ExplainState *es); +extern void ExplainIndentText(ExplainState *es); #endif /* EXPLAIN_H */ diff --git a/src/include/executor/execParallel.h b/src/include/executor/execParallel.h index 39a8792a31..02699828a2 100644 --- a/src/include/executor/execParallel.h +++ b/src/include/executor/execParallel.h @@ -27,6 +27,7 @@ typedef struct ParallelExecutorInfo ParallelContext *pcxt; /* parallel context we're using */ BufferUsage *buffer_usage; /* points to bufusage area in DSM */ WalUsage *wal_usage; /* walusage area in DSM */ + char *custom_usage; /* points to custiom usage area in DSM */ SharedExecutorInstrumentation *instrumentation; /* optional */ struct SharedJitInstrumentation *jit_instrumentation; /* optional */ dsa_area *area; /* points to DSA area in DSM */ diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h index d5d69941c5..2e6a330f6f 100644 --- a/src/include/executor/instrument.h +++ b/src/include/executor/instrument.h @@ -14,7 +14,7 @@ #define INSTRUMENT_H #include "portability/instr_time.h" - +#include "nodes/pg_list.h" /* * BufferUsage and WalUsage counters keep being incremented infinitely, @@ -65,6 +65,36 @@ typedef enum InstrumentOption INSTRUMENT_ALL = PG_INT32_MAX } InstrumentOption; +/* + * Maximal total size of all custom intrumentations + */ +#define MAX_CUSTOM_INSTR_SIZE 128 + +typedef struct { + char data[MAX_CUSTOM_INSTR_SIZE]; +} CustomInstrumentationData; + +typedef void CustomResourceUsage; +typedef struct ExplainState ExplainState; +typedef void (*cust_instr_add_t)(CustomResourceUsage* dst, CustomResourceUsage const* add); +typedef void (*cust_instr_accum_t)(CustomResourceUsage* acc, CustomResourceUsage const* end, CustomResourceUsage const* start); +typedef void (*cust_instr_show_t)(ExplainState* es, CustomResourceUsage const* usage, bool planning); + +typedef struct +{ + char const* name; /* instrumentation name (as will be recongnized in EXPLAIN options */ + Size size; + CustomResourceUsage* usage; + cust_instr_add_t add; + cust_instr_accum_t accum; + cust_instr_show_t show; + bool selected; /* selected in EXPLAIN options */ +} CustomInstrumentation; + +extern PGDLLIMPORT List* pgCustInstr; /* description of custom instrumentations */ +extern Size pgCustUsageSize; + + typedef struct Instrumentation { /* Parameters set at node creation: */ @@ -90,6 +120,8 @@ typedef struct Instrumentation double nfiltered2; /* # of tuples removed by "other" quals */ BufferUsage bufusage; /* total buffer usage */ WalUsage walusage; /* total WAL usage */ + CustomInstrumentationData cust_usage_start; /* state of custom usage at start */ + CustomInstrumentationData cust_usage; /* total custom usage */ } Instrumentation; typedef struct WorkerInstrumentation @@ -101,6 +133,11 @@ typedef struct WorkerInstrumentation extern PGDLLIMPORT BufferUsage pgBufferUsage; extern PGDLLIMPORT WalUsage pgWalUsage; + +extern void RegisterCustomInsrumentation(CustomInstrumentation* inst); +extern void GetCustomInstrumentationState(char* dst); +extern void AccumulateCustomInstrumentationState(char* dst, char const* before); + extern Instrumentation *InstrAlloc(int n, int instrument_options, bool async_mode); extern void InstrInit(Instrumentation *instr, int instrument_options); @@ -110,8 +147,8 @@ extern void InstrUpdateTupleCount(Instrumentation *instr, double nTuples); extern void InstrEndLoop(Instrumentation *instr); extern void InstrAggNode(Instrumentation *dst, Instrumentation *add); extern void InstrStartParallelQuery(void); -extern void InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage); -extern void InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage); +extern void InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage, char* custusage); +extern void InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage, char* custusage); extern void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub); extern void WalUsageAccumDiff(WalUsage *dst, const WalUsage *add, -- 2.43.0 ^ permalink raw reply [nested|flat] 25+ messages in thread
end of thread, other threads:[~2023-11-29 20:03 UTC | newest] Thread overview: 25+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2021-02-27 07:45 [PATCH v2] Fix various shared memory estimates. Julien Rouhaud <[email protected]> 2023-11-29 20:03 Re: Custom explain options Pavel Stehule <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox