Skip to content

Commit d8cedf6

Browse files
committed
Clean up some really grotty coding in catcache.c, improve hashing
performance in catcache lookups.
1 parent a60c9e3 commit d8cedf6

File tree

9 files changed

+128
-131
lines changed

9 files changed

+128
-131
lines changed

src/backend/access/hash/hashfunc.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.23 2000/01/26 05:55:55 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.24 2000/02/21 03:36:46 tgl Exp $
1212
*
1313
* NOTES
1414
* These functions are stored in pg_amproc. For each operator class
@@ -146,8 +146,24 @@ hashoidvector(Oid *key)
146146
int i;
147147
uint32 result = 0;
148148

149-
for (i = 0; i < INDEX_MAX_KEYS; i++)
150-
result = result ^ (~(uint32) key[i]);
149+
for (i = INDEX_MAX_KEYS; --i >= 0; )
150+
result = (result << 1) ^ (~(uint32) key[i]);
151+
return result;
152+
}
153+
154+
/*
155+
* Note: hashint2vector currently can't be used as a user hash table
156+
* hash function, because it has no pg_proc entry. We only need it
157+
* for catcache indexing.
158+
*/
159+
uint32
160+
hashint2vector(int16 *key)
161+
{
162+
int i;
163+
uint32 result = 0;
164+
165+
for (i = INDEX_MAX_KEYS; --i >= 0; )
166+
result = (result << 1) ^ (~(uint32) key[i]);
151167
return result;
152168
}
153169

@@ -158,13 +174,10 @@ hashoidvector(Oid *key)
158174
uint32
159175
hashchar(char key)
160176
{
161-
int len;
162177
uint32 h;
163178

164-
h = 0;
165-
len = sizeof(char);
166179
/* Convert char to integer */
167-
h = h * PRIME1 ^ (key - ' ');
180+
h = (key - ' ');
168181
h %= PRIME2;
169182

170183
return h;

src/backend/utils/adt/int.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.32 2000/01/26 05:57:14 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.33 2000/02/21 03:36:48 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -144,6 +144,17 @@ int2vectorout(int16 *int2Array)
144144
return result;
145145
}
146146

147+
/*
148+
* We don't have a complete set of int2vector support routines,
149+
* but we need int2vectoreq for catcache indexing.
150+
*/
151+
bool
152+
int2vectoreq(int16 *arg1, int16 *arg2)
153+
{
154+
return (bool) (memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(int16)) == 0);
155+
}
156+
157+
147158
/*
148159
* int44in - converts "num num ..." to internal form
149160
*
@@ -169,7 +180,7 @@ int44in(char *input_string)
169180
}
170181

171182
/*
172-
* int2vectorout - converts internal form to "num num ..."
183+
* int44out - converts internal form to "num num ..."
173184
*/
174185
char *
175186
int44out(int32 *an_array)
@@ -489,13 +500,6 @@ int42ge(int32 arg1, int32 arg2)
489500
return arg1 >= arg2;
490501
}
491502

492-
493-
bool
494-
keyfirsteq(int16 *arg1, int16 arg2)
495-
{
496-
return *arg1 == arg2;
497-
}
498-
499503
/*
500504
* int[24]pl - returns arg1 + arg2
501505
* int[24]mi - returns arg1 - arg2

src/backend/utils/cache/catcache.c

Lines changed: 79 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.61 2000/02/18 09:28:53 inoue Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.62 2000/02/21 03:36:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
#include "postgres.h"
16+
1617
#include "access/genam.h"
18+
#include "access/hash.h"
1719
#include "access/heapam.h"
1820
#include "access/valid.h"
1921
#include "catalog/pg_operator.h"
@@ -28,10 +30,11 @@
2830
static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e);
2931
static Index CatalogCacheComputeHashIndex(struct catcache * cacheInP);
3032
static Index CatalogCacheComputeTupleHashIndex(struct catcache * cacheInOutP,
31-
Relation relation, HeapTuple tuple);
33+
Relation relation,
34+
HeapTuple tuple);
3235
static void CatalogCacheInitializeCache(struct catcache * cache,
33-
Relation relation);
34-
static long comphash(long l, char *v);
36+
Relation relation);
37+
static uint32 cc_hashname(NameData *n);
3538

3639
/* ----------------
3740
* variables, macros and other stuff
@@ -63,14 +66,15 @@ GlobalMemory CacheCxt; /* context in which caches are allocated */
6366
/* ----------------
6467
* EQPROC is used in CatalogCacheInitializeCache to find the equality
6568
* functions for system types that are used as cache key fields.
69+
* See also GetCCHashFunc, which should support the same set of types.
6670
*
6771
* XXX this should be replaced by catalog lookups,
6872
* but that seems to pose considerable risk of circularity...
6973
* ----------------
7074
*/
7175
static const Oid eqproc[] = {
7276
F_BOOLEQ, InvalidOid, F_CHAREQ, F_NAMEEQ, InvalidOid,
73-
F_INT2EQ, F_KEYFIRSTEQ, F_INT4EQ, F_OIDEQ, F_TEXTEQ,
77+
F_INT2EQ, F_INT2VECTOREQ, F_INT4EQ, F_OIDEQ, F_TEXTEQ,
7478
F_OIDEQ, InvalidOid, InvalidOid, InvalidOid, F_OIDVECTOREQ
7579
};
7680

@@ -80,6 +84,54 @@ static const Oid eqproc[] = {
8084
* internal support functions
8185
* ----------------------------------------------------------------
8286
*/
87+
88+
static CCHashFunc
89+
GetCCHashFunc(Oid keytype)
90+
{
91+
switch (keytype)
92+
{
93+
case BOOLOID:
94+
case CHAROID:
95+
return (CCHashFunc) hashchar;
96+
case NAMEOID:
97+
return (CCHashFunc) cc_hashname;
98+
case INT2OID:
99+
return (CCHashFunc) hashint2;
100+
case INT2VECTOROID:
101+
return (CCHashFunc) hashint2vector;
102+
case INT4OID:
103+
return (CCHashFunc) hashint4;
104+
case TEXTOID:
105+
return (CCHashFunc) hashtext;
106+
case REGPROCOID:
107+
case OIDOID:
108+
return (CCHashFunc) hashoid;
109+
case OIDVECTOROID:
110+
return (CCHashFunc) hashoidvector;
111+
default:
112+
elog(FATAL, "GetCCHashFunc: type %u unsupported as catcache key",
113+
keytype);
114+
return NULL;
115+
}
116+
}
117+
118+
static uint32
119+
cc_hashname(NameData *n)
120+
{
121+
/*
122+
* We need our own variant of hashname because we want to accept
123+
* null-terminated C strings as search values for name fields.
124+
* So, we have to make sure the data is correctly padded before
125+
* we compute the hash value.
126+
*/
127+
NameData my_n;
128+
129+
namestrcpy(&my_n, NameStr(*n));
130+
131+
return hashname(&my_n);
132+
}
133+
134+
83135
/* --------------------------------
84136
* CatalogCacheInitializeCache
85137
* --------------------------------
@@ -190,31 +242,20 @@ CatalogCacheInitializeCache(struct catcache * cache,
190242

191243
if (cache->cc_key[i] > 0)
192244
{
245+
Oid keytype = tupdesc->attrs[cache->cc_key[i] - 1]->atttypid;
193246

194-
/*
195-
* Yoiks. The implementation of the hashing code and the
196-
* implementation of int2vector's are at loggerheads. The right
197-
* thing to do is to throw out the implementation of int2vector's
198-
* altogether; until that happens, we do the right thing here
199-
* to guarantee that the hash key generator doesn't try to
200-
* dereference an int2 by mistake.
201-
*/
247+
cache->cc_hashfunc[i] = GetCCHashFunc(keytype);
202248

203-
if (tupdesc->attrs[cache->cc_key[i] - 1]->atttypid == INT2VECTOROID)
204-
cache->cc_klen[i] = sizeof(short);
205-
else
206-
cache->cc_klen[i] = tupdesc->attrs[cache->cc_key[i] - 1]->attlen;
207-
208-
cache->cc_skey[i].sk_procedure = EQPROC(tupdesc->attrs[cache->cc_key[i] - 1]->atttypid);
249+
/* If GetCCHashFunc liked the type, safe to index into eqproc[] */
250+
cache->cc_skey[i].sk_procedure = EQPROC(keytype);
209251

210252
fmgr_info(cache->cc_skey[i].sk_procedure,
211253
&cache->cc_skey[i].sk_func);
212254
cache->cc_skey[i].sk_nargs = cache->cc_skey[i].sk_func.fn_nargs;
213255

214-
CACHE5_elog(DEBUG, "CatalogCacheInit %s %d %d %x",
256+
CACHE4_elog(DEBUG, "CatalogCacheInit %s %d %x",
215257
RelationGetRelationName(relation),
216258
i,
217-
tupdesc->attrs[cache->cc_key[i] - 1]->attlen,
218259
cache);
219260
}
220261
}
@@ -255,94 +296,44 @@ CatalogCacheInitializeCache(struct catcache * cache,
255296
MemoryContextSwitchTo(oldcxt);
256297
}
257298

258-
/* ----------------
259-
* comphash
260-
* Compute a hash value, somehow.
261-
*
262-
* XXX explain algorithm here.
263-
*
264-
* l is length of the attribute value, v
265-
* v is the attribute value ("Datum")
266-
* ----------------
267-
*/
268-
static long
269-
comphash(long l, char *v)
270-
{
271-
long i;
272-
NameData n;
273-
274-
CACHE3_elog(DEBUG, "comphash (%d,%x)", l, v);
275-
276-
switch (l)
277-
{
278-
case 1:
279-
case 2:
280-
case 4:
281-
return (long) v;
282-
}
283-
284-
if (l == NAMEDATALEN)
285-
{
286-
287-
/*
288-
* if it's a name, make sure that the values are null-padded.
289-
*
290-
* Note that this other fixed-length types can also have the same
291-
* typelen so this may break them - XXX
292-
*/
293-
namestrcpy(&n, v);
294-
v = NameStr(n);
295-
}
296-
else if (l < 0)
297-
l = VARSIZE(v);
298-
299-
i = 0;
300-
while (l--)
301-
i += *v++;
302-
return i;
303-
}
304-
305299
/* --------------------------------
306300
* CatalogCacheComputeHashIndex
307301
* --------------------------------
308302
*/
309303
static Index
310304
CatalogCacheComputeHashIndex(struct catcache * cacheInP)
311305
{
312-
Index hashIndex;
306+
uint32 hashIndex = 0;
313307

314-
hashIndex = 0x0;
315-
CACHE6_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %d %d %x",
308+
CACHE4_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %x",
316309
cacheInP->cc_relname,
317310
cacheInP->cc_nkeys,
318-
cacheInP->cc_klen[0],
319-
cacheInP->cc_klen[1],
320311
cacheInP);
321312

322313
switch (cacheInP->cc_nkeys)
323314
{
324315
case 4:
325-
hashIndex ^= comphash(cacheInP->cc_klen[3],
326-
(char *) cacheInP->cc_skey[3].sk_argument) << 9;
316+
hashIndex ^=
317+
(*cacheInP->cc_hashfunc[3])(cacheInP->cc_skey[3].sk_argument) << 9;
327318
/* FALLTHROUGH */
328319
case 3:
329-
hashIndex ^= comphash(cacheInP->cc_klen[2],
330-
(char *) cacheInP->cc_skey[2].sk_argument) << 6;
320+
hashIndex ^=
321+
(*cacheInP->cc_hashfunc[2])(cacheInP->cc_skey[2].sk_argument) << 6;
331322
/* FALLTHROUGH */
332323
case 2:
333-
hashIndex ^= comphash(cacheInP->cc_klen[1],
334-
(char *) cacheInP->cc_skey[1].sk_argument) << 3;
324+
hashIndex ^=
325+
(*cacheInP->cc_hashfunc[1])(cacheInP->cc_skey[1].sk_argument) << 3;
335326
/* FALLTHROUGH */
336327
case 1:
337-
hashIndex ^= comphash(cacheInP->cc_klen[0],
338-
(char *) cacheInP->cc_skey[0].sk_argument);
328+
hashIndex ^=
329+
(*cacheInP->cc_hashfunc[0])(cacheInP->cc_skey[0].sk_argument);
339330
break;
340331
default:
341332
elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys);
342333
break;
343334
}
344-
hashIndex %= cacheInP->cc_size;
345-
return hashIndex;
335+
hashIndex %= (uint32) cacheInP->cc_size;
336+
return (Index) hashIndex;
346337
}
347338

348339
/* --------------------------------
@@ -645,8 +636,8 @@ do { \
645636
cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \
646637
for (i = 0; i < nkeys; i += 1) \
647638
{ \
648-
elog(DEBUG, "InitSysCache: key=%d len=%d skey=[%d %d %d %d]\n", \
649-
cp->cc_key[i], cp->cc_klen[i], \
639+
elog(DEBUG, "InitSysCache: key=%d skey=[%d %d %d %d]\n", \
640+
cp->cc_key[i], \
650641
cp->cc_skey[i].sk_flags, \
651642
cp->cc_skey[i].sk_attno, \
652643
cp->cc_skey[i].sk_procedure, \
@@ -742,7 +733,8 @@ InitSysCache(char *relname,
742733
cp->cc_iscanfunc = iScanfuncP;
743734

744735
/* ----------------
745-
* initialize the cache's key information
736+
* partially initialize the cache's key information
737+
* CatalogCacheInitializeCache() will do the rest
746738
* ----------------
747739
*/
748740
for (i = 0; i < nkeys; ++i)
@@ -756,15 +748,7 @@ InitSysCache(char *relname,
756748
elog(FATAL, "InitSysCache: called with %d key[%d]", key[i], i);
757749
else
758750
{
759-
cp->cc_klen[i] = sizeof(Oid);
760-
761-
/*
762-
* ScanKeyEntryData and struct skey are equivalent. It
763-
* looks like a move was made to obsolete struct skey, but
764-
* it didn't reach this file. Someday we should clean up
765-
* this code and consolidate to ScanKeyEntry - mer 10 Nov
766-
* 1991
767-
*/
751+
cp->cc_hashfunc[i] = GetCCHashFunc(OIDOID);
768752
ScanKeyEntryInitialize(&cp->cc_skey[i],
769753
(bits16) 0,
770754
(AttrNumber) key[i],

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy