]> granicus.if.org Git - postgresql/commitdiff
Tweak dynahash.c to not allocate so many entries at once when dealing
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 26 Jun 2005 23:32:34 +0000 (23:32 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 26 Jun 2005 23:32:34 +0000 (23:32 +0000)
with a table that has a small predicted size.  Avoids wasting several
hundred K on the timezone hash table, which is likely to have only one
or a few entries, but the entries use up 10Kb apiece ...

src/backend/utils/hash/dynahash.c
src/include/utils/hsearch.h
src/timezone/pgtz.c

index 9555e25d3021572c9e082fc22531908071e0f1df..5124fe1efdba1aa298cdb51a5287ddc009add9e0 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/hash/dynahash.c,v 1.62 2005/06/18 20:51:30 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/hash/dynahash.c,v 1.63 2005/06/26 23:32:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -311,6 +311,7 @@ init_htab(HTAB *hashp, long nelem)
 {
        HASHHDR    *hctl = hashp->hctl;
        HASHSEGMENT *segp;
+       long            lnbuckets;
        int                     nbuckets;
        int                     nsegs;
 
@@ -319,9 +320,9 @@ init_htab(HTAB *hashp, long nelem)
         * number of buckets.  Allocate space for the next greater power of
         * two number of buckets
         */
-       nelem = (nelem - 1) / hctl->ffactor + 1;
+       lnbuckets = (nelem - 1) / hctl->ffactor + 1;
 
-       nbuckets = 1 << my_log2(nelem);
+       nbuckets = 1 << my_log2(lnbuckets);
 
        hctl->max_bucket = hctl->low_mask = nbuckets - 1;
        hctl->high_mask = (nbuckets << 1) - 1;
@@ -363,6 +364,10 @@ init_htab(HTAB *hashp, long nelem)
                        return false;
        }
 
+       /* Choose number of entries to allocate at a time */
+       hctl->nelem_alloc = (int) Min(nelem, HASHELEMENT_ALLOC_MAX);
+       hctl->nelem_alloc = Max(hctl->nelem_alloc, 1);
+
 #if HASH_DEBUG
        fprintf(stderr, "init_htab:\n%s%p\n%s%ld\n%s%ld\n%s%d\n%s%ld\n%s%u\n%s%x\n%s%x\n%s%ld\n%s%ld\n",
                        "TABLE POINTER   ", hashp,
@@ -394,7 +399,8 @@ hash_estimate_size(long num_entries, Size entrysize)
                                nSegments,
                                nDirEntries,
                                nElementAllocs,
-                               elementSize;
+                               elementSize,
+                               elementAllocCnt;
 
        /* estimate number of buckets wanted */
        nBuckets = 1L << my_log2((num_entries - 1) / DEF_FFACTOR + 1);
@@ -411,10 +417,12 @@ hash_estimate_size(long num_entries, Size entrysize)
        size += MAXALIGN(nDirEntries * sizeof(HASHSEGMENT));
        /* segments */
        size += nSegments * MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET));
-       /* elements --- allocated in groups of HASHELEMENT_ALLOC_INCR */
+       /* elements --- allocated in groups of up to HASHELEMENT_ALLOC_MAX */
        elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize);
-       nElementAllocs = (num_entries - 1) / HASHELEMENT_ALLOC_INCR + 1;
-       size += nElementAllocs * HASHELEMENT_ALLOC_INCR * elementSize;
+       elementAllocCnt = Min(num_entries, HASHELEMENT_ALLOC_MAX);
+       elementAllocCnt = Max(elementAllocCnt, 1);
+       nElementAllocs = (num_entries - 1) / elementAllocCnt + 1;
+       size += nElementAllocs * elementAllocCnt * elementSize;
 
        return size;
 }
@@ -633,7 +641,7 @@ hash_search(HTAB *hashp,
                        if (currBucket == NULL)
                        {
                                /* no free elements.  allocate another chunk of buckets */
-                               if (!element_alloc(hashp, HASHELEMENT_ALLOC_INCR))
+                               if (!element_alloc(hashp, hctl->nelem_alloc))
                                {
                                        /* out of memory */
                                        if (action == HASH_ENTER_NULL)
index 5bd693063acf9cef083eab7286a0e4d11d670a39..b4bede7666e64a68a2f87663f3e3e085607aca61 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/hsearch.h,v 1.38 2005/06/18 20:51:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/hsearch.h,v 1.39 2005/06/26 23:32:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -97,6 +97,7 @@ typedef struct HASHHDR
        Size            entrysize;              /* total user element size in bytes */
        long            max_dsize;              /* 'dsize' limit if directory is fixed
                                                                 * size */
+       int                     nelem_alloc;    /* number of entries to allocate at once */
        HASHELEMENT *freeList;          /* linked list of free elements */
 #ifdef HASH_STATISTICS
        long            accesses;
@@ -158,8 +159,8 @@ typedef struct HASHCTL
 
 /* max_dsize value to indicate expansible directory */
 #define NO_MAX_DSIZE                   (-1)
-/* number of hash elements allocated at once */
-#define HASHELEMENT_ALLOC_INCR (32)
+/* max number of hash elements allocated at once */
+#define HASHELEMENT_ALLOC_MAX  (32)
 
 /* hash_search operations */
 typedef enum
index 20f4b898c01148541c44ea973aacec374048993e..305bea2e5ebda486f0b4a8bdf68c6ae7a583412b 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.35 2005/06/20 08:00:51 neilc Exp $
+ *       $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.36 2005/06/26 23:32:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -978,7 +978,7 @@ init_timezone_hashtable(void)
        hash_ctl.entrysize = sizeof(pg_tz);
 
        timezone_cache = hash_create("Timezones",
-                                                                31,
+                                                                4,
                                                                 &hash_ctl,
                                                                 HASH_ELEM);
        if (!timezone_cache)