streamly-0.10.0: benchmark/Streamly/Benchmark/Unicode/Parser.hs
-- |
-- 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