Skip to content

Commit 4a14f13

Browse files
committed
Improve hash_create's API for selecting simple-binary-key hash functions.
Previously, if you wanted anything besides C-string hash keys, you had to specify a custom hashing function to hash_create(). Nearly all such callers were specifying tag_hash or oid_hash; which is tedious, and rather error-prone, since a caller could easily miss the opportunity to optimize by using hash_uint32 when appropriate. Replace this with a design whereby callers using simple binary-data keys just specify HASH_BLOBS and don't need to mess with specific support functions. hash_create() itself will take care of optimizing when the key size is four bytes. This nets out saving a few hundred bytes of code space, and offers a measurable performance improvement in tidbitmap.c (which was not exploiting the opportunity to use hash_uint32 for its 4-byte keys). There might be some wins elsewhere too, I didn't analyze closely. In future we could look into offering a similar optimized hashing function for 8-byte keys. Under this design that could be done in a centralized and machine-independent fashion, whereas getting it right for keys of platform-dependent sizes would've been notationally painful before. For the moment, the old way still works fine, so as not to break source code compatibility for loadable modules. Eventually we might want to remove tag_hash and friends from the exported API altogether, since there's no real need for them to be explicitly referenced from outside dynahash.c. Teodor Sigaev and Tom Lane
1 parent ba94518 commit 4a14f13

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+127
-155
lines changed

contrib/pg_trgm/trgm_regexp.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -915,11 +915,10 @@ transformGraph(TrgmNFA *trgmNFA)
915915
hashCtl.keysize = sizeof(TrgmStateKey);
916916
hashCtl.entrysize = sizeof(TrgmState);
917917
hashCtl.hcxt = CurrentMemoryContext;
918-
hashCtl.hash = tag_hash;
919918
trgmNFA->states = hash_create("Trigram NFA",
920919
1024,
921920
&hashCtl,
922-
HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION);
921+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
923922

924923
/* Create initial state: ambiguous prefix, NFA's initial state */
925924
MemSet(&initkey, 0, sizeof(initkey));

contrib/postgres_fdw/connection.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,11 @@ GetConnection(ForeignServer *server, UserMapping *user,
109109
MemSet(&ctl, 0, sizeof(ctl));
110110
ctl.keysize = sizeof(ConnCacheKey);
111111
ctl.entrysize = sizeof(ConnCacheEntry);
112-
ctl.hash = tag_hash;
113112
/* allocate ConnectionHash in the cache context */
114113
ctl.hcxt = CacheMemoryContext;
115114
ConnectionHash = hash_create("postgres_fdw connections", 8,
116115
&ctl,
117-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
116+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
118117

119118
/*
120119
* Register some callback functions that manage connection cleanup.

src/backend/access/gist/gistbuild.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -1142,12 +1142,10 @@ gistInitParentMap(GISTBuildState *buildstate)
11421142
hashCtl.keysize = sizeof(BlockNumber);
11431143
hashCtl.entrysize = sizeof(ParentMapEntry);
11441144
hashCtl.hcxt = CurrentMemoryContext;
1145-
hashCtl.hash = oid_hash;
11461145
buildstate->parentMap = hash_create("gistbuild parent map",
11471146
1024,
11481147
&hashCtl,
1149-
HASH_ELEM | HASH_CONTEXT
1150-
| HASH_FUNCTION);
1148+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
11511149
}
11521150

11531151
static void

src/backend/access/gist/gistbuildbuffers.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,14 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
7676
* nodeBuffersTab hash is association between index blocks and it's
7777
* buffers.
7878
*/
79+
memset(&hashCtl, 0, sizeof(hashCtl));
7980
hashCtl.keysize = sizeof(BlockNumber);
8081
hashCtl.entrysize = sizeof(GISTNodeBuffer);
8182
hashCtl.hcxt = CurrentMemoryContext;
82-
hashCtl.hash = tag_hash;
83-
hashCtl.match = memcmp;
8483
gfbb->nodeBuffersTab = hash_create("gistbuildbuffers",
8584
1024,
8685
&hashCtl,
87-
HASH_ELEM | HASH_CONTEXT
88-
| HASH_FUNCTION | HASH_COMPARE);
86+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
8987

9088
gfbb->bufferEmptyingQueue = NIL;
9189

src/backend/access/heap/rewriteheap.c

+3-5
Original file line numberDiff line numberDiff line change
@@ -283,21 +283,20 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
283283
hash_ctl.keysize = sizeof(TidHashKey);
284284
hash_ctl.entrysize = sizeof(UnresolvedTupData);
285285
hash_ctl.hcxt = state->rs_cxt;
286-
hash_ctl.hash = tag_hash;
287286

288287
state->rs_unresolved_tups =
289288
hash_create("Rewrite / Unresolved ctids",
290289
128, /* arbitrary initial size */
291290
&hash_ctl,
292-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
291+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
293292

294293
hash_ctl.entrysize = sizeof(OldToNewMappingData);
295294

296295
state->rs_old_new_tid_map =
297296
hash_create("Rewrite / Old to new tid map",
298297
128, /* arbitrary initial size */
299298
&hash_ctl,
300-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
299+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
301300

302301
MemoryContextSwitchTo(old_cxt);
303302

@@ -834,13 +833,12 @@ logical_begin_heap_rewrite(RewriteState state)
834833
hash_ctl.keysize = sizeof(TransactionId);
835834
hash_ctl.entrysize = sizeof(RewriteMappingFile);
836835
hash_ctl.hcxt = state->rs_cxt;
837-
hash_ctl.hash = tag_hash;
838836

839837
state->rs_logical_mappings =
840838
hash_create("Logical rewrite mapping",
841839
128, /* arbitrary initial size */
842840
&hash_ctl,
843-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
841+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
844842
}
845843

846844
/*

src/backend/access/transam/xlogutils.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,11 @@ log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno,
107107
memset(&ctl, 0, sizeof(ctl));
108108
ctl.keysize = sizeof(xl_invalid_page_key);
109109
ctl.entrysize = sizeof(xl_invalid_page);
110-
ctl.hash = tag_hash;
111110

112111
invalid_page_tab = hash_create("XLOG invalid-page table",
113112
100,
114113
&ctl,
115-
HASH_ELEM | HASH_FUNCTION);
114+
HASH_ELEM | HASH_BLOBS);
116115
}
117116

118117
/* we currently assume xl_invalid_page_key contains no padding */

src/backend/commands/sequence.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -986,10 +986,9 @@ create_seq_hashtable(void)
986986
memset(&ctl, 0, sizeof(ctl));
987987
ctl.keysize = sizeof(Oid);
988988
ctl.entrysize = sizeof(SeqTableData);
989-
ctl.hash = oid_hash;
990989

991990
seqhashtab = hash_create("Sequence values", 16, &ctl,
992-
HASH_ELEM | HASH_FUNCTION);
991+
HASH_ELEM | HASH_BLOBS);
993992
}
994993

995994
/*

src/backend/nodes/tidbitmap.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,11 @@ tbm_create_pagetable(TIDBitmap *tbm)
221221
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
222222
hash_ctl.keysize = sizeof(BlockNumber);
223223
hash_ctl.entrysize = sizeof(PagetableEntry);
224-
hash_ctl.hash = tag_hash;
225224
hash_ctl.hcxt = tbm->mcxt;
226225
tbm->pagetable = hash_create("TIDBitmap",
227226
128, /* start small and extend */
228227
&hash_ctl,
229-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
228+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
230229

231230
/* If entry1 is valid, push it into the hashtable */
232231
if (tbm->status == TBM_ONE_PAGE)

src/backend/optimizer/util/predtest.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -1711,9 +1711,8 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
17111711
MemSet(&ctl, 0, sizeof(ctl));
17121712
ctl.keysize = sizeof(OprProofCacheKey);
17131713
ctl.entrysize = sizeof(OprProofCacheEntry);
1714-
ctl.hash = tag_hash;
17151714
OprProofCacheHash = hash_create("Btree proof lookup cache", 256,
1716-
&ctl, HASH_ELEM | HASH_FUNCTION);
1715+
&ctl, HASH_ELEM | HASH_BLOBS);
17171716

17181717
/* Arrange to flush cache on pg_amop changes */
17191718
CacheRegisterSyscacheCallback(AMOPOPID,

src/backend/parser/parse_oper.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -1059,9 +1059,8 @@ find_oper_cache_entry(OprCacheKey *key)
10591059
MemSet(&ctl, 0, sizeof(ctl));
10601060
ctl.keysize = sizeof(OprCacheKey);
10611061
ctl.entrysize = sizeof(OprCacheEntry);
1062-
ctl.hash = tag_hash;
10631062
OprCacheHash = hash_create("Operator lookup cache", 256,
1064-
&ctl, HASH_ELEM | HASH_FUNCTION);
1063+
&ctl, HASH_ELEM | HASH_BLOBS);
10651064

10661065
/* Arrange to flush cache on pg_operator and pg_cast changes */
10671066
CacheRegisterSyscacheCallback(OPERNAMENSP,

src/backend/postmaster/autovacuum.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -922,10 +922,9 @@ rebuild_database_list(Oid newdb)
922922
*/
923923
hctl.keysize = sizeof(Oid);
924924
hctl.entrysize = sizeof(avl_dbase);
925-
hctl.hash = oid_hash;
926925
hctl.hcxt = tmpcxt;
927926
dbhash = hash_create("db hash", 20, &hctl, /* magic number here FIXME */
928-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
927+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
929928

930929
/* start by inserting the new database */
931930
score = 0;
@@ -1997,12 +1996,11 @@ do_autovacuum(void)
19971996
MemSet(&ctl, 0, sizeof(ctl));
19981997
ctl.keysize = sizeof(Oid);
19991998
ctl.entrysize = sizeof(av_relation);
2000-
ctl.hash = oid_hash;
20011999

20022000
table_toast_map = hash_create("TOAST to main relid map",
20032001
100,
20042002
&ctl,
2005-
HASH_ELEM | HASH_FUNCTION);
2003+
HASH_ELEM | HASH_BLOBS);
20062004

20072005
/*
20082006
* Scan pg_class to determine which tables to vacuum.

src/backend/postmaster/checkpointer.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -1212,13 +1212,12 @@ CompactCheckpointerRequestQueue(void)
12121212
MemSet(&ctl, 0, sizeof(ctl));
12131213
ctl.keysize = sizeof(CheckpointerRequest);
12141214
ctl.entrysize = sizeof(struct CheckpointerSlotMapping);
1215-
ctl.hash = tag_hash;
12161215
ctl.hcxt = CurrentMemoryContext;
12171216

12181217
htab = hash_create("CompactCheckpointerRequestQueue",
12191218
CheckpointerShmem->num_requests,
12201219
&ctl,
1221-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
1220+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
12221221

12231222
/*
12241223
* The basic idea here is that a request can be skipped if it's followed

src/backend/postmaster/pgstat.c

+7-14
Original file line numberDiff line numberDiff line change
@@ -1132,12 +1132,11 @@ pgstat_collect_oids(Oid catalogid)
11321132
memset(&hash_ctl, 0, sizeof(hash_ctl));
11331133
hash_ctl.keysize = sizeof(Oid);
11341134
hash_ctl.entrysize = sizeof(Oid);
1135-
hash_ctl.hash = oid_hash;
11361135
hash_ctl.hcxt = CurrentMemoryContext;
11371136
htab = hash_create("Temporary table of OIDs",
11381137
PGSTAT_TAB_HASH_SIZE,
11391138
&hash_ctl,
1140-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
1139+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
11411140

11421141
rel = heap_open(catalogid, AccessShareLock);
11431142
snapshot = RegisterSnapshot(GetLatestSnapshot());
@@ -1520,11 +1519,10 @@ pgstat_init_function_usage(FunctionCallInfoData *fcinfo,
15201519
memset(&hash_ctl, 0, sizeof(hash_ctl));
15211520
hash_ctl.keysize = sizeof(Oid);
15221521
hash_ctl.entrysize = sizeof(PgStat_BackendFunctionEntry);
1523-
hash_ctl.hash = oid_hash;
15241522
pgStatFunctions = hash_create("Function stat entries",
15251523
PGSTAT_FUNCTION_HASH_SIZE,
15261524
&hash_ctl,
1527-
HASH_ELEM | HASH_FUNCTION);
1525+
HASH_ELEM | HASH_BLOBS);
15281526
}
15291527

15301528
/* Get the stats entry for this function, create if necessary */
@@ -3483,19 +3481,17 @@ reset_dbentry_counters(PgStat_StatDBEntry *dbentry)
34833481
memset(&hash_ctl, 0, sizeof(hash_ctl));
34843482
hash_ctl.keysize = sizeof(Oid);
34853483
hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
3486-
hash_ctl.hash = oid_hash;
34873484
dbentry->tables = hash_create("Per-database table",
34883485
PGSTAT_TAB_HASH_SIZE,
34893486
&hash_ctl,
3490-
HASH_ELEM | HASH_FUNCTION);
3487+
HASH_ELEM | HASH_BLOBS);
34913488

34923489
hash_ctl.keysize = sizeof(Oid);
34933490
hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry);
3494-
hash_ctl.hash = oid_hash;
34953491
dbentry->functions = hash_create("Per-database function",
34963492
PGSTAT_FUNCTION_HASH_SIZE,
34973493
&hash_ctl,
3498-
HASH_ELEM | HASH_FUNCTION);
3494+
HASH_ELEM | HASH_BLOBS);
34993495
}
35003496

35013497
/*
@@ -3902,10 +3898,9 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
39023898
memset(&hash_ctl, 0, sizeof(hash_ctl));
39033899
hash_ctl.keysize = sizeof(Oid);
39043900
hash_ctl.entrysize = sizeof(PgStat_StatDBEntry);
3905-
hash_ctl.hash = oid_hash;
39063901
hash_ctl.hcxt = pgStatLocalContext;
39073902
dbhash = hash_create("Databases hash", PGSTAT_DB_HASH_SIZE, &hash_ctl,
3908-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
3903+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
39093904

39103905
/*
39113906
* Clear out global and archiver statistics so they start from zero in
@@ -4026,21 +4021,19 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
40264021
memset(&hash_ctl, 0, sizeof(hash_ctl));
40274022
hash_ctl.keysize = sizeof(Oid);
40284023
hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
4029-
hash_ctl.hash = oid_hash;
40304024
hash_ctl.hcxt = pgStatLocalContext;
40314025
dbentry->tables = hash_create("Per-database table",
40324026
PGSTAT_TAB_HASH_SIZE,
40334027
&hash_ctl,
4034-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
4028+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
40354029

40364030
hash_ctl.keysize = sizeof(Oid);
40374031
hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry);
4038-
hash_ctl.hash = oid_hash;
40394032
hash_ctl.hcxt = pgStatLocalContext;
40404033
dbentry->functions = hash_create("Per-database function",
40414034
PGSTAT_FUNCTION_HASH_SIZE,
40424035
&hash_ctl,
4043-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
4036+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
40444037

40454038
/*
40464039
* If requested, read the data from the database-specific

src/backend/replication/logical/reorderbuffer.c

+3-6
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,10 @@ ReorderBufferAllocate(void)
245245

246246
hash_ctl.keysize = sizeof(TransactionId);
247247
hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt);
248-
hash_ctl.hash = tag_hash;
249248
hash_ctl.hcxt = buffer->context;
250249

251250
buffer->by_txn = hash_create("ReorderBufferByXid", 1000, &hash_ctl,
252-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
251+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
253252

254253
buffer->by_txn_last_xid = InvalidTransactionId;
255254
buffer->by_txn_last_txn = NULL;
@@ -1111,7 +1110,6 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
11111110

11121111
hash_ctl.keysize = sizeof(ReorderBufferTupleCidKey);
11131112
hash_ctl.entrysize = sizeof(ReorderBufferTupleCidEnt);
1114-
hash_ctl.hash = tag_hash;
11151113
hash_ctl.hcxt = rb->context;
11161114

11171115
/*
@@ -1120,7 +1118,7 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
11201118
*/
11211119
txn->tuplecid_hash =
11221120
hash_create("ReorderBufferTupleCid", txn->ntuplecids, &hash_ctl,
1123-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
1121+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
11241122

11251123
dlist_foreach(iter, &txn->tuplecids)
11261124
{
@@ -2434,10 +2432,9 @@ ReorderBufferToastInitHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
24342432
memset(&hash_ctl, 0, sizeof(hash_ctl));
24352433
hash_ctl.keysize = sizeof(Oid);
24362434
hash_ctl.entrysize = sizeof(ReorderBufferToastEnt);
2437-
hash_ctl.hash = tag_hash;
24382435
hash_ctl.hcxt = rb->context;
24392436
txn->toast_hash = hash_create("ReorderBufferToastHash", 5, &hash_ctl,
2440-
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
2437+
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
24412438
}
24422439

24432440
/*

src/backend/storage/buffer/buf_table.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,12 @@ InitBufTable(int size)
5959
/* BufferTag maps to Buffer */
6060
info.keysize = sizeof(BufferTag);
6161
info.entrysize = sizeof(BufferLookupEnt);
62-
info.hash = tag_hash;
6362
info.num_partitions = NUM_BUFFER_PARTITIONS;
6463

6564
SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
6665
size, size,
6766
&info,
68-
HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
67+
HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
6968
}
7069

7170
/*

src/backend/storage/buffer/bufmgr.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -2063,10 +2063,9 @@ InitBufferPoolAccess(void)
20632063
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
20642064
hash_ctl.keysize = sizeof(int32);
20652065
hash_ctl.entrysize = sizeof(PrivateRefCountArray);
2066-
hash_ctl.hash = oid_hash; /* a bit more efficient than tag_hash */
20672066

20682067
PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
2069-
HASH_ELEM | HASH_FUNCTION);
2068+
HASH_ELEM | HASH_BLOBS);
20702069
}
20712070

20722071
/*

src/backend/storage/buffer/localbuf.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,11 @@ InitLocalBuffers(void)
415415
MemSet(&info, 0, sizeof(info));
416416
info.keysize = sizeof(BufferTag);
417417
info.entrysize = sizeof(LocalBufferLookupEnt);
418-
info.hash = tag_hash;
419418

420419
LocalBufHash = hash_create("Local Buffer Lookup Table",
421420
nbufs,
422421
&info,
423-
HASH_ELEM | HASH_FUNCTION);
422+
HASH_ELEM | HASH_BLOBS);
424423

425424
if (!LocalBufHash)
426425
elog(ERROR, "could not initialize local buffer hash table");

0 commit comments

Comments
 (0)