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)