diff --git a/src/ballet/murmur3/fd_murmur3.c b/src/ballet/murmur3/fd_murmur3.c index 2eecdfc635..34d02ee589 100644 --- a/src/ballet/murmur3/fd_murmur3.c +++ b/src/ballet/murmur3/fd_murmur3.c @@ -1,9 +1,9 @@ #include "fd_murmur3.h" -uint -fd_murmur3_32( void const * _data, - ulong sz, - uint seed ) { +static uint +fd_murmur3_32_( void const * _data, + ulong sz, + uint seed ) { uchar const * data = _data; uint sz_tag = (uint)sz; @@ -53,3 +53,9 @@ fd_murmur3_32( void const * _data, return hash; } +uint +fd_murmur3_32( void const * _data, + ulong sz, + uint seed ) { + return fd_murmur3_32_( _data, sz, seed ); +} diff --git a/src/ballet/murmur3/fd_murmur3.h b/src/ballet/murmur3/fd_murmur3.h index b9b8e7eafb..8a6a5b0694 100644 --- a/src/ballet/murmur3/fd_murmur3.h +++ b/src/ballet/murmur3/fd_murmur3.h @@ -18,6 +18,57 @@ fd_murmur3_32( void const * data, ulong sz, uint seed ); +/* fd_pchash computes the hash of a program counter suitable for use as + the call instruction immediate. Equivalent to fd_murmur3_32 with + zero seed and pc serialized to little-endian ulong. */ + +static inline uint +fd_pchash( uint pc ) { + uint x = pc; + x *= 0xcc9e2d51U; + x = fd_uint_rotate_left( x, 15 ); + x *= 0x1b873593U; + x = fd_uint_rotate_left( x, 13 ); + x *= 5; + x += 0xe6546b64U; + x = fd_uint_rotate_left( x, 13 ); + x *= 5; + x += 0xe6546b64U; + x ^= 8; + x ^= x >> 16; + x *= 0x85ebca6bU; + x ^= x >> 13; + x *= 0xc2b2ae35U; + x ^= x >> 16; + return x; +} + +/* Inverse of the above. E.g.: + fd_pchash_inverse( fd_pchash( (uint)x ) )==(uint)x + and: + fd_pchash( fd_pchash_inverse( (uint)x ) )==(uint)x */ + +static inline uint +fd_pchash_inverse( uint hash ) { + uint x = hash; + x ^= x >> 16; + x *= 0x7ed1b41dU; + x ^= (x >> 13) ^ (x >> 26); + x *= 0xa5cb9243U; + x ^= x >> 16; + x ^= 8; + x -= 0xe6546b64U; + x *= 0xcccccccdU; + x = fd_uint_rotate_right( x, 13 ); + x -= 0xe6546b64U; + x *= 0xcccccccdU; + x = fd_uint_rotate_right( x, 13 ); + x *= 0x56ed309bU; + x = fd_uint_rotate_right( x, 15 ); + x *= 0xdee13bb1U; + return x; +} + FD_PROTOTYPES_END #endif /* HEADER_fd_src_ballet_murmur3_fd_murmur3_h */ diff --git a/src/ballet/murmur3/test_murmur3.c b/src/ballet/murmur3/test_murmur3.c index adc5e5c472..7d69c2547d 100644 --- a/src/ballet/murmur3/test_murmur3.c +++ b/src/ballet/murmur3/test_murmur3.c @@ -64,49 +64,98 @@ main( int argc, "\n\t\t", sz, hash, expected )); } - FD_LOG_NOTICE(( "Benchmarking small inputs" )); - - /* warmup */ - uint hash = 42U; - for( ulong i=0UL; i<100000UL; i++ ) { - uint x[2] = { (uint)i, hash }; - hash = fd_murmur3_32( &x, 8UL, 0 ); + for( uint i=0U; i<10U<<17; i++ ) { + ulong pc = i; + uint hash = fd_murmur3_32( &pc, 8UL, 0U ); + FD_TEST( fd_pchash( i )==hash ); + FD_TEST( fd_pchash_inverse( hash )==i ); } - /* for real */ - ulong bench_cnt = 100000000UL; - long dt = -fd_log_wallclock(); - for( ulong i=0UL; i