Permalink
Browse files

Try different methods of hashing integers.

Preliminary results on my laptop:

Status quo (id):     9 ns
Wang 32-bit (best): 12
Jenkins 32-bit:     13
Wang 64-bit:        14
SipHash 32-bit:     33
SipHash 64-bit:     36
  • Loading branch information...
1 parent 93d1bb4 commit 6881817a19f53a959d7981da2acfa633e333506f @bos committed Oct 13, 2012
Showing with 115 additions and 7 deletions.
  1. +46 −7 benchmarks/Benchmarks.hs
  2. +46 −0 benchmarks/cbits/inthash.c
  3. +1 −0 benchmarks/hashable-benchmarks.cabal
  4. +22 −0 cbits/siphash.c
@@ -7,6 +7,7 @@ import Control.Monad.ST
import Criterion.Main
import Data.Hashable
import Data.Hashable.SipHash
+import Data.Int
import Foreign.ForeignPtr
import GHC.Exts
import GHC.ST (ST(..))
@@ -61,6 +62,10 @@ main = do
sse41SipHash (PS fp off len) =
inlinePerformIO . withForeignPtr fp $ \ptr ->
return $! sse41_siphash k0 k1 (ptr `plusPtr` off) (fromIntegral len)
+ cSipHash8 v = c_siphash24_u8 k0 k1 (fromIntegral v)
+ cSipHash16 v = c_siphash24_u16 k0 k1 (fromIntegral v)
+ cSipHash32 v = c_siphash24_u32 k0 k1 (fromIntegral v)
+ cSipHash64 v = c_siphash24_u64 k0 k1 (fromIntegral v)
withForeignPtr fp5 $ \ p5 ->
withForeignPtr fp8 $ \ p8 ->
@@ -98,6 +103,11 @@ main = do
, bench "512" $ whnf hash bs512
, bench "2^20" $ whnf hash bs1Mb
]
+ , bench "Int8" $ whnf hash (0xef :: Int8)
+ , bench "Int16" $ whnf hash (0x7eef :: Int16)
+ , bench "Int32" $ whnf hash (0x7eadbeef :: Int32)
+ , bench "Int" $ whnf hash (0x7eadbeefdeadbeef :: Int)
+ , bench "Int64" $ whnf hash (0x7eadbeefdeadbeef :: Int64)
]
, bgroup "sipHash"
[ bench "5" $ whnf sipHash bs5
@@ -118,13 +128,19 @@ main = do
, bench "2^20" $ whnf cSipHash bs1Mb
]
, bgroup "cSipHash24"
- [ bench "5" $ whnf cSipHash24 bs5
- , bench "8" $ whnf cSipHash24 bs8
- , bench "11" $ whnf cSipHash24 bs11
- , bench "40" $ whnf cSipHash24 bs40
- , bench "128" $ whnf cSipHash24 bs128
- , bench "512" $ whnf cSipHash24 bs512
- , bench "2^20" $ whnf cSipHash24 bs1Mb
+ [ bgroup "ByteString"
+ [ bench "5" $ whnf cSipHash24 bs5
+ , bench "8" $ whnf cSipHash24 bs8
+ , bench "11" $ whnf cSipHash24 bs11
+ , bench "40" $ whnf cSipHash24 bs40
+ , bench "128" $ whnf cSipHash24 bs128
+ , bench "512" $ whnf cSipHash24 bs512
+ , bench "2^20" $ whnf cSipHash24 bs1Mb
+ ]
+ , bench "Int8" $ whnf cSipHash8 (0x5a :: Int8)
+ , bench "Int16" $ whnf cSipHash16 (0x5a5a :: Int16)
+ , bench "Int32" $ whnf cSipHash32 (0x5a5a5a5a :: Int32)
+ , bench "Int64" $ whnf cSipHash64 (0x5a5a5a5a5a5a5a5a :: Int64)
]
, bgroup "sse41SipHash"
[ bench "5" $ whnf sse41SipHash bs5
@@ -144,6 +160,12 @@ main = do
, bench "512" $ whnf hsSipHash bs512
, bench "2^20" $ whnf hsSipHash bs1Mb
]
+ , bgroup "Int"
+ [ bench "wang32" $ whnf hash_wang_32 0xdeadbeef
+ , bench "wang64" $ whnf hash_wang_64 0xdeadbeefdeadbeef
+ , bench "jenkins32a" $ whnf hash_jenkins_32a 0xdeadbeef
+ , bench "jenkins32b" $ whnf hash_jenkins_32b 0xdeadbeef
+ ]
]
data ByteArray = BA { unBA :: !ByteArray# }
@@ -158,5 +180,22 @@ foreign import ccall unsafe "hashable_siphash" c_siphash
:: CInt -> CInt -> Word64 -> Word64 -> Ptr Word8 -> CSize -> Word64
foreign import ccall unsafe "hashable_siphash24" c_siphash24
:: Word64 -> Word64 -> Ptr Word8 -> CSize -> Word64
+foreign import ccall unsafe "hashable_siphash24_u64" c_siphash24_u64
+ :: Word64 -> Word64 -> Word64 -> Word64
+foreign import ccall unsafe "hashable_siphash24_u32" c_siphash24_u32
+ :: Word64 -> Word64 -> Word32 -> Word64
+foreign import ccall unsafe "hashable_siphash24_u16" c_siphash24_u16
+ :: Word64 -> Word64 -> Word16 -> Word64
+foreign import ccall unsafe "hashable_siphash24_u8" c_siphash24_u8
+ :: Word64 -> Word64 -> Word8 -> Word64
foreign import ccall unsafe "siphash_sse41" sse41_siphash
:: Word64 -> Word64 -> Ptr Word8 -> CSize -> Word64
+
+foreign import ccall unsafe "hash_wang_32" hash_wang_32
+ :: Word32 -> Word32
+foreign import ccall unsafe "hash_wang_64" hash_wang_64
+ :: Word64 -> Word64
+foreign import ccall unsafe "hash_jenkins_32a" hash_jenkins_32a
+ :: Word32 -> Word32
+foreign import ccall unsafe "hash_jenkins_32b" hash_jenkins_32b
+ :: Word32 -> Word32
@@ -0,0 +1,46 @@
+#include <stdint.h>
+
+uint32_t hash_wang_32(uint32_t a)
+{
+ a = (a ^ 61) ^ (a >> 16);
+ a = a + (a << 3);
+ a = a ^ (a >> 4);
+ a = a * 0x27d4eb2d;
+ a = a ^ (a >> 15);
+ return a;
+}
+
+uint64_t hash_wang_64(uint64_t key)
+{
+ key = (~key) + (key << 21); // key = (key << 21) - key - 1;
+ key = key ^ ((key >> 24) | (key << 40));
+ key = (key + (key << 3)) + (key << 8); // key * 265
+ key = key ^ ((key >> 14) | (key << 50));
+ key = (key + (key << 2)) + (key << 4); // key * 21
+ key = key ^ ((key >> 28) | (key << 36));
+ key = key + (key << 31);
+ return key;
+}
+
+uint32_t hash_jenkins_32a(uint32_t a)
+{
+ a = (a+0x7ed55d16) + (a<<12);
+ a = (a^0xc761c23c) ^ (a>>19);
+ a = (a+0x165667b1) + (a<<5);
+ a = (a+0xd3a2646c) ^ (a<<9);
+ a = (a+0xfd7046c5) + (a<<3);
+ a = (a^0xb55a4f09) ^ (a>>16);
+ return a;
+}
+
+uint32_t hash_jenkins_32b(uint32_t a)
+{
+ a -= (a<<6);
+ a ^= (a>>17);
+ a -= (a<<9);
+ a ^= (a<<4);
+ a -= (a<<3);
+ a ^= (a<<10);
+ a ^= (a>>15);
+ return a;
+}
@@ -11,6 +11,7 @@ executable hashable-benchmarks
../cbits/hashByteString.c
../cbits/getRandomBytes.c
../cbits/siphash.c
+ cbits/inthash.c
cbits/siphash-sse41.c
hs-source-dirs: .. .
main-is: Benchmarks.hs
View
@@ -4,6 +4,8 @@
#include <stdint.h>
typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
typedef uint8_t u8;
#define ROTL(x,b) (u64)(((x) << (b)) | ((x) >> (64 - (b))))
@@ -92,3 +94,23 @@ u64 hashable_siphash24_offset(u64 k0, u64 k1,
{
return _siphash(2, 4, k0, k1, str + off, len);
}
+
+u64 hashable_siphash24_u8(u64 k0, u64 k1, u8 key)
+{
+ return _siphash(2, 4, k0, k1, (const u8 *) &key, sizeof(u8));
+}
+
+u16 hashable_siphash24_u16(u64 k0, u64 k1, u16 key)
+{
+ return _siphash(2, 4, k0, k1, (const u8 *) &key, sizeof(u16));
+}
+
+u16 hashable_siphash24_u32(u64 k0, u64 k1, u32 key)
+{
+ return _siphash(2, 4, k0, k1, (const u8 *) &key, sizeof(u32));
+}
+
+u64 hashable_siphash24_u64(u64 k0, u64 k1, u64 key)
+{
+ return _siphash(2, 4, k0, k1, (const u8 *) &key, sizeof(u64));
+}

0 comments on commit 6881817

Please sign in to comment.