Interpretation of PostgreSQL Source Code-Buffer Manager#8 (BufTableHashCode function)
This section briefly introduces the implementation function ReadBuffer_common- > BufferAlloc- > BufTableHashCode in PostgreSQL cache management (Buffer Manager), which calculates HashCode based on BufferTag.
I. data structure
BufferDesc
Shared descriptor (status) data for shared buffer
/ * * Flags for buffer descriptors * buffer descriptor tag * * Note: TAG_VALID essentially means that there is a buffer hashtable * entry associated with the buffer's tag. * Note: TAG_VALID essentially means that there is a buffer hash table entry associated with the token of the buffer. * / / buffer header Lock # define BM_LOCKED (1U hash (keyPtr, hashp- > keysize);} / * * tag_hash: hash function for fixed-size tag values * tag_hash: fixed tag size hash function * / uint32tag_hash (const void * key, Size keysize) {return DatumGetUInt32 (hash_any ((const unsigned char *) key, (int) keysize)) } / * * DatumGetUInt32 * Returns 32-bit unsigned integer value of a datum. * DatumGetUInt32 returns the 32-bit unsigned integer value of datum * / # define DatumGetUInt32 (X) ((uint32) (X))
Hash_any
The hash_any function hash a variable length key value to a 32-bit value
/ * * hash_any ()-- hash a variable-length key into a 32-bit value * k: the key (the unaligned variable-length array of bytes) * len: the length of the key, counting by bytes * hash_any ()-- hash a variable length key value to a 32-bit value. * k: the key (unaligned variable length byte array) * * Returns a uint32 value. Every bit of the key affects every bit of * the return value. Every 1-bit and 2-bit delta achieves avalanche. * About 6*len+35 instructions. The best hash table sizes are powers * of 2.There is no need to do mod a prime (mod is sooo slow!). * If you need less than 32 bits, use a bitmask. * returns an unsigned 32-bit integer value. * every bit of key affects every bit of the return value. Each 1-bit and 2-bit increment produces an avalanche. * there are about 6*len+35 instructions. The best hash table size is a power of 2. There is no need for slow mod operations. * if you need a value less than 32bits, use bitmask. * * This procedure must never throw elog (ERROR); the ResourceOwner code * relies on this not to fail. * this process should never throw an elog (ERROR); ResourceOwner code that relies on this function will never throw an exception. * * Note: we could easily change this function to return a 64-bit hash value * by using the final values of both b and c. B is perhaps a little less * well mixed than c, however. * Note: this function cannot be easily changed. The hash value of 64-bit is returned by using the final values of b and c. The mixing degree of b may not be as good as c * / Datumhash_any (register const unsigned char * k, register int keylen) {register uint32 a, b, c, len. / * Set up the internal state * / / set the internal state, initialize a/b/c len = keylen; a = b = c = 0x9e3779b9 + len + 3923095 / * If the source pointer is word-aligned, we use word-wide fetches * / / if the source pointer is word aligned, then we use the font width to extract if (uintptr_t) k & UINT32_ALIGN_MASK) = = 0) {/ / the source data is aligned / * Code path for aligned source data * / register const uint32 * ka = (const uint32 *) k / * handle most of the key * / while (len > = 12) {a + = ka [0]; b + = ka [1]; c + = ka [2]; mix (a, b, c); ka + = 3; len-= 12 } / * handle the last 11 bytes * / process the next 11 bytes k = (const unsigned char *) ka;#ifdef WORDS_BIGENDIAN// large code side switch (len) {case 11: C + = ((uint32) k [10]