primal-memory-0.1.0.0: bench/Conversion.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main (main) where
import GHC.Exts
import Criterion.Main
import Data.Prim.Memory.Bytes
import Data.Prim.Memory.Ptr
import Control.Prim.Monad
import qualified Foreign.ForeignPtr as GHC
import Foreign.Storable
import Data.Prim.Memory.ForeignPtr
import Data.Semigroup
import qualified Data.Primitive.ByteArray as BA
main :: IO ()
main = do
let n = 1000000 :: Count a
n64 = n :: Count Word64
xs = [1 .. unCount n]
mb1 <- allocAlignedMBytes n64
b1 <- freezeMBytes mb1
mb2 <- allocAlignedMBytes n64
mb3 <- allocAlignedMBytes n64
let fp = toForeignPtrMBytes mb3
mba <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8
ba <- BA.unsafeFreezeByteArray mba
-- Ensure that arrays are equal by filling them with zeros
bEq1 <- freezeMBytes =<< callocAlignedMBytes n64
bEq2 <- freezeMBytes =<< callocAlignedMBytes n64
mbaEq1 <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8
mbaEq2 <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8
BA.setByteArray mbaEq1 0 (unCount n64) (0 :: Word64)
BA.setByteArray mbaEq2 0 (unCount n64) (0 :: Word64)
baEq1 <- BA.unsafeFreezeByteArray mbaEq1
baEq2 <- BA.unsafeFreezeByteArray mbaEq2
defaultMain
[ bgroup
"eq"
[ bench "Bytes" $ whnf (bEq1 ==) bEq2
, bench "ByteArray" $ whnf (baEq1 ==) baEq2
]
, bgroup
"with"
[ bench "direct" $ nfIO (bytesAction n64 mb1)
, bench "withPtrMBytes (INLINE)" $ nfIO (ptrAction_inline n64 mb3)
, bench "withPtrMBytes (withNoHaltPtrMBytes)" $ nfIO (ptrAction n64 mb2)
, bench "withPtrMBytes (NOINLINE)" $ nfIO (ptrAction_noinline n64 mb1)
, bench "withForeignPtr (INLINE)" $ nfIO (foreignPtrAction n64 fp)
, bench "withForeignPtr (Storable)" $ nfIO (foreignPtrStorable n64 fp)
]
, bgroup
"list"
[ bgroup
"mappend"
[ bench "Bytes" $ whnf (mappend bEq1) bEq2
, bench "ByteArray" $ whnf (mappend baEq1) baEq2
]
, bgroup
"mconcat"
[ bench "Bytes" $ whnf mconcat [bEq1, bEq2, bEq1]
, bench "ByteArray" $ whnf mconcat [baEq1, baEq2, baEq1]
]
, env (pure (5 :: Int)) $ \sLen ->
bgroup
"stimes"
[ bench "Bytes" $ whnf (stimes sLen) bEq1
, bench "ByteArray" $ whnf (stimes sLen) baEq1
]
, bgroup
"toList"
[ bench "Bytes" $ nf toList b1
, bench "ByteArray" $ nf toList ba
]
, bgroup
"fromList"
[ bench "Bytes" $ whnf (fromListBytes :: [Int] -> Bytes 'Inc) xs
, bench "ByteArray" $ whnf BA.byteArrayFromList xs
]
, bgroup
"fromListN"
[ bench "Bytes" $ whnf (fromListBytesN_ n :: [Int] -> Bytes 'Inc) xs
, bench "ByteArray" $ whnf (BA.byteArrayFromListN (unCount n)) xs
]
]
]
withPtrMBytes_noinline :: MBytes 'Pin s -> (Ptr a -> IO b) -> IO b
withPtrMBytes_noinline mb f = do
res <- f $ toPtrMBytes mb
res <$ touch mb
{-# NOINLINE withPtrMBytes_noinline #-}
ptrAction :: forall a . (Num a, Prim a) => Count a -> MBytes 'Pin RealWorld -> IO ()
ptrAction (Count n) mb = go 0
where
go i
| i < n = do
withNoHaltPtrMBytes mb $ \ptr -> (writeOffPtr ptr (Off i) (123 :: a) :: IO ())
go (i + 1)
| otherwise = pure ()
ptrAction_inline :: forall a . (Num a, Prim a) => Count a -> MBytes 'Pin RealWorld -> IO ()
ptrAction_inline (Count n) mb = go 0
where
go i
| i < n = do
withPtrMBytes mb $ \ptr -> writeOffPtr ptr (Off i) (123 :: a)
go (i + 1)
| otherwise = pure ()
ptrAction_noinline :: forall a . (Num a, Prim a) => Count a -> MBytes 'Pin RealWorld -> IO ()
ptrAction_noinline (Count n) mb = go 0
where
go i
| i < n = do
withPtrMBytes_noinline mb $ \ptr -> writeOffPtr ptr (Off i) (123 :: a)
go (i + 1)
| otherwise = pure ()
bytesAction :: forall a . (Num a, Prim a) => Count a -> MBytes 'Pin RealWorld -> IO ()
bytesAction (Count n) mb = go 0
where
go i
| i < n = do
writeOffMBytes mb (Off i) (123 :: a)
go (i + 1)
| otherwise = pure ()
foreignPtrAction :: forall a . (Num a, Prim a) => Count a -> ForeignPtr a -> IO ()
foreignPtrAction (Count n) fp = go 0
where
go i
| i < n = do
withForeignPtr fp $ \ptr -> writeOffPtr ptr (Off i) (123 :: a)
go (i + 1)
| otherwise = pure ()
foreignPtrStorable :: forall a . (Num a, Storable a) => Count a -> ForeignPtr a -> IO ()
foreignPtrStorable (Count n) fp = go 0
where
go i
| i < n = do
GHC.withForeignPtr fp $ \ptr -> pokeElemOff ptr i (123 :: a)
go (i + 1)
| otherwise = pure ()