hash.c, string.c: improve hash function quality

Use FNV-1a (xor-then-multiply) instead of FNV-1 for better avalanche
in byte hashing. Strengthen the hash finalizer in mrb_obj_hash_code()
with multiply-xorshift to improve distribution for integer and symbol
keys with power-of-two table sizes.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-04-13 16:12:00 +09:00
parent 86e274f759
commit b3777110ab
2 changed files with 8 additions and 5 deletions
+4 -1
View File
@@ -361,7 +361,10 @@ mrb_obj_hash_code(mrb_state *mrb, mrb_value key)
hash_code = U32(tt) ^ U32(mrb_integer(hash_code_obj));
break;
}
return hash_code ^ (hash_code << 2) ^ (hash_code >> 2);
hash_code ^= hash_code >> 16;
hash_code *= 0x45d9f3b;
hash_code ^= hash_code >> 16;
return hash_code;
}
static uint32_t
+4 -4
View File
@@ -2014,18 +2014,18 @@ mrb_byte_hash_step(const uint8_t *s, mrb_int len, uint32_t hval)
const uint8_t *send = s + len;
/*
* FNV-1 hash each octet in the buffer
* FNV-1a hash each octet in the buffer
*/
while (s < send) {
/* xor the bottom with the current octet */
hval ^= (uint32_t)*s++;
/* multiply by the 32-bit FNV magic prime mod 2^32 */
#if defined(NO_FNV_GCC_OPTIMIZATION)
hval *= FNV_32_PRIME;
#else
hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
#endif
/* xor the bottom with the current octet */
hval ^= (uint32_t)*s++;
}
/* return our new hash value */