packages feed

hashes-0.2.0.0: bench/Main.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

-- |
-- Module: Main
-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>
-- License: MIT
-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>
-- Stability: experimental
--
module Main
( main
) where

import Control.Monad

import Criterion
import Criterion.Main

#if defined(BENCHMARK_CRYPTONITE)
import qualified Data.ByteArray as BA
import qualified Data.ByteArray.Hash as BA
import qualified Crypto.Hash as C
#endif
import qualified Data.ByteString as B
import qualified Data.ByteString.Unsafe as B
import qualified Data.ByteString.Short as BS
import Data.Word

import GHC.Ptr

import System.IO.Unsafe

-- internal modules

import qualified Data.Hash.SipHash as SH
import qualified Data.Hash.FNV1 as FH

#if defined(WITH_OPENSSL)
import qualified Data.Hash.SHA3 as SHA3
import qualified Data.Hash.SHA2 as SHA2
import qualified Data.Hash.Blake2 as BLAKE2
import qualified Data.Hash.Keccak as K
#endif

-- -------------------------------------------------------------------------- --
-- Main

main :: IO ()
main = do
    defaultMain
        [ bgroup "sipHash" $ []
            <> [sipBench "internal" (internalSipHash 17 17)]
#if defined(BENCHMARK_CRYPTONITE)
            <> [sipBench "memory" (memorySipHash 17 17)]
#endif

        , bgroup "fnv1aHash" $ []
            <> [fnv1aBench "internal" internalFnv1a]
            <> [fnv1aBench "primitive" primitiveFnv1a]
#if defined(BENCHMARK_CRYPTONITE)
            <> [fnv1aBench "memory" memoryFnv1a]
#endif

        , bgroup "Sha2_256" $ []
#if defined(WITH_OPENSSL)
            <> [sha2_256Bench "openssl" sha2_256Ssl]
#endif
#if defined(BENCHMARK_CRYPTONITE)
            <> [sha2_256Bench "cryptonite" cryptoniteSha2_256]
#endif

        , bgroup "Sha2_512" $ []
#if defined(WITH_OPENSSL)
            <> [sha2_512Bench "openssl" sha2_512Ssl]
#endif
#if defined(BENCHMARK_CRYPTONITE)
            <> [sha2_512Bench "cryptonite" cryptoniteSha2_512]
#endif

        , bgroup "Sha3_256" $ []
#if defined(WITH_OPENSSL)
            <> [sha3_256Bench "openssl" sha3_256Ssl]
#endif
#if defined(BENCHMARK_CRYPTONITE)
            <> [sha3_256Bench "cryptonite" cryptoniteSha3_256]
#endif

        , bgroup "Sha3_512" $ []
#if defined(WITH_OPENSSL)
            <> [sha3_512Bench "openssl" sha3_512Ssl]
#endif
#if defined(BENCHMARK_CRYPTONITE)
            <> [sha3_512Bench "cryptonite" cryptoniteSha3_512]
#endif

        , bgroup "keccak256" $ []
#if defined(WITH_OPENSSL)
            <> [keccakBench "openssl" keccak256Ssl]
#endif
#if defined(BENCHMARK_CRYPTONITE)
            <> [keccakBench "cryptonite" cryptoniteKeccak256]
#endif

        , bgroup "blake2s256" $ []
#if defined(WITH_OPENSSL)
            <> [blake2s256Bench "openssl" blake2s256Ssl]
#endif
#if defined(BENCHMARK_CRYPTONITE)
            <> [blake2s256Bench "cryptonite" cryptoniteBlake2s256]
#endif

        , bgroup "blake2b512" $ []
#if defined(WITH_OPENSSL)
            <> [ blake2b512Bench "openssl" blake2b512Ssl ]
#endif
#if defined(BENCHMARK_CRYPTONITE)
            <> [ blake2b512Bench "cryptonite" cryptoniteBlake2b512 ]
#endif
        ]

-- -------------------------------------------------------------------------- --
-- SipHash

#if defined(BENCHMARK_CRYPTONITE)
memorySipHash :: BA.ByteArrayAccess p => Word64 -> Word64 -> p -> Word64
memorySipHash w0 w1 x = r
  where
    BA.SipHash r = BA.sipHash (BA.SipKey w0 w1) x
{-# INLINE memorySipHash #-}
#endif

internalSipHash :: Word64 -> Word64 -> B.ByteString -> Word64
internalSipHash w0 w1 x = r
  where
    SH.SipHash r = SH.hashByteString @(SH.SipHash 2 4) (SH.SipHashKey w0 w1) x
{-# INLINE internalSipHash #-}

sipBench :: String -> (B.ByteString -> Word64) -> Benchmark
sipBench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i

benchStrings :: [B.ByteString]
benchStrings = str <$> [0, 1, 5, 67, 300, 2000, 20000]
  where
    str (i :: Int) = B.pack $ fromIntegral <$> [0..i-1]

-- -------------------------------------------------------------------------- --
-- Fvn1Hash

#if defined(BENCHMARK_CRYPTONITE)
memoryFnv1a :: B.ByteString -> Word64
memoryFnv1a b = h
  where
    BA.FnvHash64 h = BA.fnv1a_64Hash b
{-# INLINE memoryFnv1a #-}
#endif

internalFnv1a :: B.ByteString -> Word64
internalFnv1a b = r
  where
    FH.Fnv1a64Hash r = FH.hashByteString @FH.Fnv1a64Hash b
{-# INLINE internalFnv1a #-}

primitiveFnv1a :: B.ByteString -> Word64
primitiveFnv1a b = unsafeDupablePerformIO $
    B.unsafeUseAsCStringLen b $ \(addr, n) ->
        fromIntegral <$!> FH.fnv1a_host (castPtr addr) n
{-# INLINE primitiveFnv1a #-}

fnv1aBench :: String -> (B.ByteString -> Word64) -> Benchmark
fnv1aBench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i

-- -------------------------------------------------------------------------- --
-- SHA3 256

#if defined(WITH_OPENSSL)
sha3_256Ssl :: B.ByteString -> BS.ShortByteString
sha3_256Ssl b = r
  where
    SHA3.Sha3_256  r = SHA3.hashByteString @SHA3.Sha3_256 b
{-# INLINE sha3_256Ssl #-}
#endif

#if defined(BENCHMARK_CRYPTONITE)
cryptoniteSha3_256 :: B.ByteString -> BS.ShortByteString
cryptoniteSha3_256 b = BS.toShort $ BA.convert $! C.hash @_ @C.SHA3_256 b
{-# INLINE cryptoniteSha3_256 #-}
#endif

sha3_256Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark
sha3_256Bench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i

-- -------------------------------------------------------------------------- --
-- SHA3 512

#if defined(WITH_OPENSSL)
sha3_512Ssl :: B.ByteString -> BS.ShortByteString
sha3_512Ssl b = r
  where
    SHA3.Sha3_512  r = SHA3.hashByteString @SHA3.Sha3_512 b
{-# INLINE sha3_512Ssl #-}
#endif

#if defined(BENCHMARK_CRYPTONITE)
cryptoniteSha3_512 :: B.ByteString -> BS.ShortByteString
cryptoniteSha3_512 b = BS.toShort $ BA.convert $! C.hash @_ @C.SHA3_512 b
{-# INLINE cryptoniteSha3_512 #-}
#endif

sha3_512Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark
sha3_512Bench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i

-- -------------------------------------------------------------------------- --
-- SHA2_256

#if defined(WITH_OPENSSL)
sha2_256Ssl :: B.ByteString -> BS.ShortByteString
sha2_256Ssl b = r
  where
    SHA2.Sha2_256  r = SHA3.hashByteString @SHA2.Sha2_256 b
{-# INLINE sha2_256Ssl #-}
#endif

#if defined(BENCHMARK_CRYPTONITE)
cryptoniteSha2_256 :: B.ByteString -> BS.ShortByteString
cryptoniteSha2_256 b = BS.toShort $ BA.convert $! C.hash @_ @C.SHA256 b
{-# INLINE cryptoniteSha2_256 #-}
#endif

sha2_256Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark
sha2_256Bench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i

-- -------------------------------------------------------------------------- --
-- SHA2_512

#if defined(WITH_OPENSSL)
sha2_512Ssl :: B.ByteString -> BS.ShortByteString
sha2_512Ssl b = r
  where
    SHA2.Sha2_512  r = SHA3.hashByteString @SHA2.Sha2_512 b
{-# INLINE sha2_512Ssl #-}
#endif

#if defined(BENCHMARK_CRYPTONITE)
cryptoniteSha2_512 :: B.ByteString -> BS.ShortByteString
cryptoniteSha2_512 b = BS.toShort $ BA.convert $! C.hash @_ @C.SHA512 b
{-# INLINE cryptoniteSha2_512 #-}
#endif

sha2_512Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark
sha2_512Bench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i

-- -------------------------------------------------------------------------- --
-- BLAKE2B512

#if defined(WITH_OPENSSL)
blake2b512Ssl :: B.ByteString -> BS.ShortByteString
blake2b512Ssl b = r
  where
    BLAKE2.Blake2b512  r = BLAKE2.hashByteString @BLAKE2.Blake2b512 b
{-# INLINE blake2b512Ssl #-}
#endif

#if defined(BENCHMARK_CRYPTONITE)
cryptoniteBlake2b512 :: B.ByteString -> BS.ShortByteString
cryptoniteBlake2b512 b = BS.toShort $ BA.convert $! C.hash @_ @C.Blake2b_512 b
{-# INLINE cryptoniteBlake2b512 #-}
#endif

blake2b512Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark
blake2b512Bench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i

-- -------------------------------------------------------------------------- --
-- BLAKE2S256

#if defined(WITH_OPENSSL)
blake2s256Ssl :: B.ByteString -> BS.ShortByteString
blake2s256Ssl b = r
  where
    BLAKE2.Blake2s256  r = BLAKE2.hashByteString @BLAKE2.Blake2s256 b
{-# INLINE blake2s256Ssl #-}
#endif

#if defined(BENCHMARK_CRYPTONITE)
cryptoniteBlake2s256 :: B.ByteString -> BS.ShortByteString
cryptoniteBlake2s256 b = BS.toShort $ BA.convert $! C.hash @_ @C.Blake2s_256 b
{-# INLINE cryptoniteBlake2s256 #-}
#endif

blake2s256Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark
blake2s256Bench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i

-- -------------------------------------------------------------------------- --
-- Keccak 256

#if defined(WITH_OPENSSL)
keccak256Ssl :: B.ByteString -> BS.ShortByteString
keccak256Ssl b = r
  where
    K.Keccak256  r = K.hashByteString @K.Keccak256 b
{-# INLINE keccak256Ssl #-}
#endif

#if defined(BENCHMARK_CRYPTONITE)
cryptoniteKeccak256 :: B.ByteString -> BS.ShortByteString
cryptoniteKeccak256 b = BS.toShort $ BA.convert $! C.hash @_ @C.Keccak_256 b
{-# INLINE cryptoniteKeccak256 #-}
#endif

keccakBench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark
keccakBench l f = bgroup l $ go <$> benchStrings
  where
    go i = bench (show (B.length i)) $ whnf f i