Arrange to preallocate all required space for the buffer and FSM hash

tables in shared memory.  This ensures that overflow of the lock table
creates no long-lasting problems.  Per discussion with Merlin Moncure.
This commit is contained in:
Tom Lane 2004-09-28 20:46:37 +00:00
parent d9b68c8061
commit 3a246cc285
6 changed files with 42 additions and 18 deletions

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.34 2004/08/29 05:06:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.35 2004/09/28 20:46:27 tgl Exp $
* *
* *
* NOTES: * NOTES:
@ -283,8 +283,8 @@ InitFreeSpaceMap(void)
info.hash = tag_hash; info.hash = tag_hash;
FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash", FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash",
MaxFSMRelations / 10, MaxFSMRelations + 1,
MaxFSMRelations, MaxFSMRelations + 1,
&info, &info,
(HASH_ELEM | HASH_FUNCTION)); (HASH_ELEM | HASH_FUNCTION));

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.80 2004/08/29 05:06:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.81 2004/09/28 20:46:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -262,8 +262,17 @@ InitShmemIndex(void)
* shared memory hash table. * shared memory hash table.
* *
* We assume caller is doing some kind of synchronization * We assume caller is doing some kind of synchronization
* so that two people dont try to create/initialize the * so that two people don't try to create/initialize the
* table at once. * table at once.
*
* max_size is the estimated maximum number of hashtable entries. This is
* not a hard limit, but the access efficiency will degrade if it is
* exceeded substantially (since it's used to compute directory size and
* the hash table buckets will get overfull).
*
* init_size is the number of hashtable entries to preallocate. For a table
* whose maximum size is certain, this should be equal to max_size; that
* ensures that no run-time out-of-shared-memory failures can occur.
*/ */
HTAB * HTAB *
ShmemInitHash(const char *name, /* table string name for shmem index */ ShmemInitHash(const char *name, /* table string name for shmem index */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.140 2004/09/12 18:30:50 tgl Exp $ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.141 2004/09/28 20:46:32 tgl Exp $
* *
* NOTES * NOTES
* Outside modules can create a lock table and acquire/release * Outside modules can create a lock table and acquire/release
@ -241,7 +241,7 @@ LockMethodTableInit(const char *tabName,
/* Compute init/max size to request for lock hashtables */ /* Compute init/max size to request for lock hashtables */
max_table_size = NLOCKENTS(maxBackends); max_table_size = NLOCKENTS(maxBackends);
init_table_size = max_table_size / 10; init_table_size = max_table_size / 2;
/* Allocate a string for the shmem index table lookups. */ /* Allocate a string for the shmem index table lookups. */
/* This is just temp space in this routine, so palloc is OK. */ /* This is just temp space in this routine, so palloc is OK. */

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/hash/dynahash.c,v 1.53 2004/08/29 05:06:50 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/hash/dynahash.c,v 1.54 2004/09/28 20:46:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -63,7 +63,7 @@
*/ */
static void *DynaHashAlloc(Size size); static void *DynaHashAlloc(Size size);
static HASHSEGMENT seg_alloc(HTAB *hashp); static HASHSEGMENT seg_alloc(HTAB *hashp);
static bool element_alloc(HTAB *hashp); static bool element_alloc(HTAB *hashp, int nelem);
static bool dir_realloc(HTAB *hashp); static bool dir_realloc(HTAB *hashp);
static bool expand_table(HTAB *hashp); static bool expand_table(HTAB *hashp);
static bool hdefault(HTAB *hashp); static bool hdefault(HTAB *hashp);
@ -228,11 +228,26 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
CurrentDynaHashCxt = hashp->hcxt; CurrentDynaHashCxt = hashp->hcxt;
} }
/* Build the hash directory structure */
if (!init_htab(hashp, nelem)) if (!init_htab(hashp, nelem))
{ {
hash_destroy(hashp); hash_destroy(hashp);
return NULL; return NULL;
} }
/*
* For a shared hash table, preallocate the requested number of elements.
* This reduces problems with run-time out-of-shared-memory conditions.
*/
if (flags & HASH_SHARED_MEM)
{
if (!element_alloc(hashp, (int) nelem))
{
hash_destroy(hashp);
return NULL;
}
}
return hashp; return hashp;
} }
@ -631,7 +646,7 @@ hash_search(HTAB *hashp,
if (currBucket == NULL) if (currBucket == NULL)
{ {
/* no free elements. allocate another chunk of buckets */ /* no free elements. allocate another chunk of buckets */
if (!element_alloc(hashp)) if (!element_alloc(hashp, HASHELEMENT_ALLOC_INCR))
return NULL; /* out of memory */ return NULL; /* out of memory */
currBucket = hctl->freeList; currBucket = hctl->freeList;
Assert(currBucket != NULL); Assert(currBucket != NULL);
@ -898,7 +913,7 @@ seg_alloc(HTAB *hashp)
* allocate some new elements and link them into the free list * allocate some new elements and link them into the free list
*/ */
static bool static bool
element_alloc(HTAB *hashp) element_alloc(HTAB *hashp, int nelem)
{ {
HASHHDR *hctl = hashp->hctl; HASHHDR *hctl = hashp->hctl;
Size elementSize; Size elementSize;
@ -910,13 +925,13 @@ element_alloc(HTAB *hashp)
CurrentDynaHashCxt = hashp->hcxt; CurrentDynaHashCxt = hashp->hcxt;
tmpElement = (HASHELEMENT *) tmpElement = (HASHELEMENT *)
hashp->alloc(HASHELEMENT_ALLOC_INCR * elementSize); hashp->alloc(nelem * elementSize);
if (!tmpElement) if (!tmpElement)
return false; return false;
/* link all the new entries into the freelist */ /* link all the new entries into the freelist */
for (i = 0; i < HASHELEMENT_ALLOC_INCR; i++) for (i = 0; i < nelem; i++)
{ {
tmpElement->link = hctl->freeList; tmpElement->link = hctl->freeList;
hctl->freeList = tmpElement; hctl->freeList = tmpElement;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.42 2004/08/29 04:13:10 momjian Exp $ * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.43 2004/09/28 20:46:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -73,8 +73,8 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr);
/* size constants for the shmem index table */ /* size constants for the shmem index table */
/* max size of data structure string name */ /* max size of data structure string name */
#define SHMEM_INDEX_KEYSIZE (48) #define SHMEM_INDEX_KEYSIZE (48)
/* maximum size of the shmem index table */ /* max size of the shmem index table (not a hard limit) */
#define SHMEM_INDEX_SIZE (100) #define SHMEM_INDEX_SIZE (32)
/* this is a hash bucket in the shmem index table */ /* this is a hash bucket in the shmem index table */
typedef struct typedef struct

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/hsearch.h,v 1.32 2004/08/29 05:06:59 momjian Exp $ * $PostgreSQL: pgsql/src/include/utils/hsearch.h,v 1.33 2004/09/28 20:46:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -135,7 +135,7 @@ typedef struct HASHCTL
#define HASH_FFACTOR 0x008 /* Set fill factor */ #define HASH_FFACTOR 0x008 /* Set fill factor */
#define HASH_FUNCTION 0x010 /* Set user defined hash function */ #define HASH_FUNCTION 0x010 /* Set user defined hash function */
#define HASH_ELEM 0x020 /* Set key/entry size */ #define HASH_ELEM 0x020 /* Set key/entry size */
#define HASH_SHARED_MEM 0x040 /* Set shared mem const */ #define HASH_SHARED_MEM 0x040 /* Hashtable is in shared memory */
#define HASH_ATTACH 0x080 /* Do not initialize hctl */ #define HASH_ATTACH 0x080 /* Do not initialize hctl */
#define HASH_ALLOC 0x100 /* Set memory allocator */ #define HASH_ALLOC 0x100 /* Set memory allocator */
#define HASH_CONTEXT 0x200 /* Set explicit memory context */ #define HASH_CONTEXT 0x200 /* Set explicit memory context */