-- | -- Module : Streamly.Benchmark.Data.Parser -- Copyright : (c) 2020 Composewell Technologies -- -- License : BSD-3-Clause -- Maintainer : streamly@composewell.com {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wno-orphans #-} #undef FUSION_CHECK #ifdef FUSION_CHECK {-# OPTIONS_GHC -ddump-simpl -ddump-to-file -dsuppress-all #-} #endif module Main ( main ) where import Control.DeepSeq (NFData(..)) import Control.Monad (replicateM_) import Streamly.Internal.Data.Parser (ParseError(..)) import Streamly.Internal.Data.Stream (Stream) import Prelude hiding (any, all, take, sequence, sequence_, sequenceA, takeWhile, dropWhile) import qualified Streamly.Data.Array as Array import qualified Streamly.Data.Stream as Stream import qualified Streamly.Internal.Unicode.Parser as PRU import Test.Tasty.Bench hiding (env) import Streamly.Benchmark.Common runParser :: Int -> (Stream IO Char -> IO a) -> IO () runParser count p = do let v = "+123456789.123456789e-123" let !(arr :: Array.Array Char) = Array.fromListN (length v) v let s = Stream.unfold Array.reader arr replicateM_ count (p s) -- | Takes a fold method, and uses it with a default source. {-# INLINE benchIOSink #-} benchIOSink :: Int -> String -> (Stream IO Char -> IO b) -> Benchmark benchIOSink value name f = bench name $ nfIO $ runParser value f {-# INLINE doubleParser #-} doubleParser :: Monad m => Stream m Char -> m (Either ParseError (Int, Int)) doubleParser = Stream.parse PRU.doubleParser {-# INLINE number #-} number :: Monad m => Stream m Char -> m (Either ParseError (Integer, Int)) number = Stream.parse PRU.number {-# INLINE double #-} double :: Monad m => Stream m Char -> m (Either ParseError Double) double = Stream.parse PRU.double {-# INLINE numberDouble #-} numberDouble :: Monad m => Stream m Char -> m (Either ParseError Double) numberDouble = Stream.parse p where p = uncurry PRU.mkDouble <$> PRU.number ------------------------------------------------------------------------------- -- Benchmarks ------------------------------------------------------------------------------- moduleName :: String moduleName = "Unicode.Parser" instance NFData ParseError where {-# INLINE rnf #-} rnf (ParseError x) = rnf x o_n_heap_serial :: Int -> [Benchmark] o_n_heap_serial value = [ benchIOSink value "doubleParser" doubleParser , benchIOSink value "number" number , benchIOSink value "double (doubleParser)" double , benchIOSink value "double (number)" numberDouble ] ------------------------------------------------------------------------------- -- Driver ------------------------------------------------------------------------------- main :: IO () main = do #ifndef FUSION_CHECK runWithCLIOpts defaultStreamSize allBenchmarks where allBenchmarks value = [ bgroup (o_n_heap_prefix moduleName) (o_n_heap_serial value) ] #else -- Enable FUSION_CHECK macro at the beginning of the file -- Enable one benchmark below, and run the benchmark -- Check the .dump-simpl output let value = 100000 runParser value double return () #endif