{-# LANGUAGE DeriveGeneric #-} module Main (main) where import Control.Applicative import Control.DeepSeq import Control.Monad import Control.Monad.ST import Criterion import Criterion.Main (defaultMain) import Data.ByteArraySlice.Unsafe import Data.Tuple.Fields import Data.Tuple.ST import Data.Word import GHC.Generics main :: IO () main = defaultMain [ bench "uninlined" $ nf uninlined 10000 , bench "inlined" $ nf inlined 10000 ] data Uninlined = Uninlined {-# UNPACK #-} !Char {-# UNPACK #-} !Int {-# UNPACK #-} !Word {-# UNPACK #-} !Float {-# UNPACK #-} !Double deriving Generic instance ByteArraySlice Uninlined instance Fields Uninlined instance NFData Uninlined uninlined :: Int -> [Uninlined] uninlined n = runST $ do vs <- replicateM n $ newSTUTuple $ Uninlined 'a' n (fromIntegral n) (fromIntegral n) (fromIntegral n) let n' = n + 1 forM_ vs $ \ v -> do write1 v 'b' write2 v n' write3 v (fromIntegral n') write4 v (fromIntegral n') write5 v (fromIntegral n') forM vs $ \ v -> Uninlined <$> read1 v <*> read2 v <*> read3 v <*> read4 v <*> read5 v data Inlined = Inlined {-# UNPACK #-} !Char {-# UNPACK #-} !Int {-# UNPACK #-} !Word {-# UNPACK #-} !Float {-# UNPACK #-} !Double deriving Generic instance ByteArraySlice Inlined where {-# INLINE plusByteSize #-} {-# INLINE readByteOff #-} {-# INLINE writeByteOff #-} instance Fields Inlined instance NFData Inlined inlined :: Int -> [Inlined] inlined n = runST $ do vs <- replicateM n $ newSTUTuple $ Inlined 'a' n (fromIntegral n) (fromIntegral n) (fromIntegral n) let n' = n + 1 forM_ vs $ \ v -> do write1 v 'b' write2 v n' write3 v (fromIntegral n') write4 v (fromIntegral n') write5 v (fromIntegral n') forM vs $ \ v -> Inlined <$> read1 v <*> read2 v <*> read3 v <*> read4 v <*> read5 v newSTUTuple :: (ByteArraySlice a, Fields a) => a -> ST s (STUTuple s a) newSTUTuple = thawTuple