add linear-async, base streams benchmark reporting

split linear to separate serial and parallel modules. Parallel modules use
lower number of elements in the stream so that they can run faster.
This commit is contained in:
Harendra Kumar 2018-10-09 12:48:53 +05:30
parent 54bb7ea8fd
commit a929a1682c
10 changed files with 359 additions and 299 deletions

View File

@ -39,8 +39,7 @@ set_benchmarks() {
# $1: benchmark name (linear, nested, base)
find_report_prog() {
local bench_name=$1
local prog_name="chart-$bench_name"
local prog_name="chart"
hash -r
local prog_path=$($STACK exec which $prog_name)
if test -x "$prog_path"
@ -53,8 +52,7 @@ find_report_prog() {
# $1: benchmark name (linear, nested, base)
build_report_prog() {
local bench_name=$1
local prog_name="chart-$bench_name"
local prog_name="chart"
local prog_path=$($STACK exec which $prog_name)
hash -r
@ -71,18 +69,13 @@ build_report_prog() {
}
build_report_progs() {
local bench_list=$1
if test "$RAW" = "0"
then
for i in $bench_list
do
build_report_prog $i || exit 1
build_report_prog || exit 1
local prog
prog=$(find_report_prog $i) || \
die "Cannot find bench-graph executable for benchmark $i"
prog=$(find_report_prog) || \
die "Cannot find bench-graph executable"
echo "Using bench-graph executable [$prog]"
done
fi
}
@ -198,25 +191,16 @@ run_measurements() {
fi
}
run_report() {
local bench_name=$1
local input_file=$2
if test "$RAW" = "0"
then
local prog
prog=$(find_report_prog $bench_name) || \
die "Cannot find bench-graph executable for benchmark $bench_name"
echo
echo "Generating reports for ${bench_name}..."
$prog
fi
}
run_reports() {
local prog
prog=$(find_report_prog) || \
die "Cannot find bench-graph executable"
echo
for i in $1
do
run_report $i
echo "Generating reports for ${i}..."
$prog --benchmark $i
done
}
@ -290,4 +274,7 @@ fi
# Run reports
#-----------------------------------------------------------------------------
if test "$RAW" = "0"
then
run_reports "$BENCHMARKS"
fi

187
benchmark/Chart.hs Normal file
View File

@ -0,0 +1,187 @@
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Control.Exception (handle, catch, SomeException, ErrorCall(..))
import Control.Monad.Trans.State
import Control.Monad.Trans.Maybe
import Data.List
import Data.List.Split
import Data.Ord (comparing)
import System.Environment (getArgs)
import Control.Monad.IO.Class (liftIO)
import Control.Monad (mzero)
import BenchGraph
------------------------------------------------------------------------------
-- Command line parsing
------------------------------------------------------------------------------
data BenchType = Linear | LinearAsync | Nested | Base
data Options = Options
{ genGraphs :: Bool
, benchType :: BenchType
}
defaultOptions = Options False Linear
setGenGraphs val = do
(args, opts) <- get
put (args, opts { genGraphs = val })
setBenchType val = do
(args, opts) <- get
put (args, opts { benchType = val })
-- Like the shell "shift" to shift the command line arguments
shift :: StateT ([String], Options) (MaybeT IO) (Maybe String)
shift = do
s <- get
case s of
([], _) -> return Nothing
(x : xs, opts) -> put (xs, opts) >> return (Just x)
parseBench :: StateT ([String], Options) (MaybeT IO) ()
parseBench = do
x <- shift
case x of
Just "linear" -> setBenchType Linear
Just "linear-async" -> setBenchType LinearAsync
Just "nested" -> setBenchType Nested
Just "base" -> setBenchType Base
Just str -> do
liftIO $ putStrLn $ "unrecognized benchmark type " ++ str
mzero
Nothing -> do
liftIO $ putStrLn $ "please provide a benchmark type "
mzero
-- totally imperative style option parsing
parseOptions :: IO (Maybe Options)
parseOptions = do
args <- getArgs
runMaybeT $ flip evalStateT (args, defaultOptions) $ do
x <- shift
case x of
Just "--graphs" -> setGenGraphs True
Just "--benchmark" -> parseBench
Just str -> do
liftIO $ putStrLn $ "Unrecognized option " ++ str
mzero
Nothing -> return ()
fmap snd get
ignoringErr a = catch a (\(ErrorCall err :: ErrorCall) ->
putStrLn $ "Failed with error:\n" ++ err ++ "\nSkipping.")
------------------------------------------------------------------------------
-- Linear composition charts
------------------------------------------------------------------------------
makeLinearGraphs :: Config -> String -> IO ()
makeLinearGraphs cfg inputFile = do
ignoringErr $ graph inputFile "operations" $ cfg
{ title = Just "Streamly operations"
, classifyBenchmark = \b ->
if (not $ "serially/" `isPrefixOf` b)
|| "/generation" `isInfixOf` b
|| "/compose" `isInfixOf` b
|| "/concat" `isSuffixOf` b
then Nothing
else Just ("Streamly", last $ splitOn "/" b)
}
ignoringErr $ graph inputFile "generation" $ cfg
{ title = Just "Stream generation"
, classifyBenchmark = \b ->
if "serially/generation" `isPrefixOf` b
then Just ("Streamly", last $ splitOn "/" b)
else Nothing
}
ignoringErr $ graph inputFile "composition" $ cfg
{ title = Just "Streamly composition performance"
, classifyBenchmark = fmap ("Streamly",) . stripPrefix "serially/compose/"
}
ignoringErr $ graph inputFile "composition-scaling"
$ cfg
{ title = Just "Streamly composition scaling"
, classifyBenchmark = fmap ("Streamly",) . stripPrefix "serially/compose-"
}
------------------------------------------------------------------------------
-- Nested composition charts
------------------------------------------------------------------------------
makeNestedGraphs :: Config -> String -> IO ()
makeNestedGraphs cfg inputFile = do
ignoringErr $ graph inputFile "nested-serial-diff" $ cfg
{ title = Just "Nested serial"
, classifyBenchmark = \b ->
let ls = splitOn "/" b
in case head ls of
"serially" -> Just (head ls, last ls)
_ -> Nothing
}
------------------------------------------------------------------------------
-- Charts for parallel streams
------------------------------------------------------------------------------
makeLinearAsyncGraphs :: Config -> String -> IO ()
makeLinearAsyncGraphs cfg inputFile = do
putStrLn "Not implemented"
return ()
------------------------------------------------------------------------------
-- Charts for base streams
------------------------------------------------------------------------------
makeBaseGraphs :: Config -> String -> IO ()
makeBaseGraphs cfg inputFile = do
putStrLn "Not implemented"
return ()
------------------------------------------------------------------------------
-- text reports
------------------------------------------------------------------------------
benchShow Options{..} cfg func inp out =
if genGraphs
then func cfg {outputDir = Just out} inp
else
ignoringErr $ report inp Nothing $ cfg
{ selectBenchmarks =
\f ->
reverse $ map fst $
sortBy (comparing snd) $ f $ ColumnIndex 1
}
main :: IO ()
main = do
let cfg = defaultConfig { presentation = Groups PercentDiff }
res <- parseOptions
case res of
Nothing -> do
putStrLn "cannot parse options"
return ()
Just opts@Options{..} -> do
case benchType of
Linear -> benchShow opts cfg makeLinearGraphs
"charts/linear/results.csv"
"charts/linear"
LinearAsync -> benchShow opts cfg makeLinearAsyncGraphs
"charts/linear-async/results.csv"
"charts/linear-async"
Nested -> benchShow opts cfg makeNestedGraphs
"charts/nested/results.csv"
"charts/nested"
Base -> benchShow opts cfg makeBaseGraphs
"charts/base/results.csv"
"charts/base"

View File

@ -1,90 +0,0 @@
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Control.Exception (handle, catch, SomeException, ErrorCall(..))
import Control.Monad.Trans.State
import Control.Monad.Trans.Maybe
import Data.List
import Data.List.Split
import Data.Ord (comparing)
import System.Environment (getArgs)
import Control.Monad.IO.Class (liftIO)
import Control.Monad (mzero)
import BenchGraph
import Utils
ignoringErr a = catch a (\(ErrorCall err :: ErrorCall) ->
putStrLn $ "Failed with error:\n" ++ err ++ "\nSkipping.")
makeGraphs cfg = do
ignoringErr $ graph inputFile "operations" $ cfg
{ title = Just "Streamly operations"
, classifyBenchmark = \b ->
if (not $ "serially/" `isPrefixOf` b)
|| "/generation" `isInfixOf` b
|| "/compose" `isInfixOf` b
|| "/concat" `isSuffixOf` b
then Nothing
else Just ("Streamly", last $ splitOn "/" b)
}
ignoringErr $ graph inputFile "generation" $ cfg
{ title = Just "Stream generation"
, classifyBenchmark = \b ->
if "serially/generation" `isPrefixOf` b
then Just ("Streamly", last $ splitOn "/" b)
else Nothing
}
ignoringErr $ graph inputFile "composition" $ cfg
{ title = Just "Streamly composition performance"
, classifyBenchmark = fmap ("Streamly",) . stripPrefix "serially/compose/"
}
ignoringErr $ graph inputFile "composition-scaling"
$ cfg
{ title = Just "Streamly composition scaling"
, classifyBenchmark = fmap ("Streamly",) . stripPrefix "serially/compose-"
}
inputFile :: String
inputFile = "charts/linear/results.csv"
-- Primitive command line options parsing
data Options = Options
{ genGraphs :: Bool
}
main :: IO ()
main = do
let cfg = defaultConfig
{ outputDir = Just "charts/linear"
, presentation = Groups PercentDiff
}
args <- getArgs
res <- runMaybeT $ flip evalStateT args $ do
x <- shift
case x of
Just "--graphs" -> return $ Options { genGraphs = True }
Nothing -> return $ Options { genGraphs = False }
Just str -> do
liftIO $ putStrLn $ "Unrecognized option " ++ str
mzero
case res of
Nothing -> return ()
Just Options{..} ->
if genGraphs
then makeGraphs cfg
else
ignoringErr $ report inputFile Nothing $ cfg
{ selectBenchmarks =
\f ->
reverse $ map fst $
sortBy (comparing snd) $ f $ ColumnIndex 1
}

View File

@ -1,70 +0,0 @@
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Control.Exception (handle, catch, SomeException, ErrorCall)
import Control.Monad.Trans.State
import Control.Monad.Trans.Maybe
import Data.List
import Data.List.Split
import Data.Ord (comparing)
import System.Environment (getArgs)
import Control.Monad.IO.Class (liftIO)
import Control.Monad (mzero)
import BenchGraph
import Utils
ignoringErr a = catch a (\(_ :: ErrorCall) ->
putStrLn "Failed. Skipping.")
makeGraphs :: Config -> IO ()
makeGraphs cfg = do
ignoringErr $ graph inputFile "nested-serial-diff" $ cfg
{ title = Just "Nested serial"
, classifyBenchmark = \b ->
let ls = splitOn "/" b
in case head ls of
"serially" -> Just (head ls, last ls)
_ -> Nothing
}
-- Primitive command line options parsing
data Options = Options
{ genGraphs :: Bool
}
inputFile :: String
inputFile = "charts/nested/results.csv"
main :: IO ()
main = do
let cfg = defaultConfig
{ outputDir = Just "charts/nested"
, presentation = Groups PercentDiff
}
args <- getArgs
res <- runMaybeT $ flip evalStateT args $ do
x <- shift
case x of
Just "--graphs" -> return $ Options { genGraphs = True }
Nothing -> return $ Options { genGraphs = False }
Just str -> do
liftIO $ putStrLn $ "Unrecognized option " ++ str
mzero
case res of
Nothing -> return ()
Just Options{..} ->
if genGraphs
then makeGraphs cfg
else
ignoringErr $ report inputFile Nothing $ cfg
{ selectBenchmarks =
\f ->
reverse $ map fst $
sortBy (comparing snd) $ f $ ColumnIndex 1
}

View File

@ -19,7 +19,7 @@ import Gauge
-- | Takes a fold method, and uses it with a default source.
{-# INLINE benchIO #-}
benchIO :: (IsStream t, NFData b) => String -> (t IO Int -> IO b) -> Benchmark
benchIO name f = bench name $ nfIO $ randomRIO (1,1000) >>= f . Ops.source
benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source
-- | Takes a source, and uses it with a default drain/fold method.
{-# INLINE benchSrcIO #-}
@ -29,7 +29,7 @@ benchSrcIO
-> (Int -> t IO Int)
-> Benchmark
benchSrcIO t name f
= bench name $ nfIO $ randomRIO (1,1000) >>= Ops.toNull t . f
= bench name $ nfIO $ randomRIO (1,1) >>= Ops.toNull t . f
{-
_benchId :: NFData b => String -> (Ops.Stream m Int -> Identity b) -> Benchmark
@ -123,77 +123,4 @@ main = do
, benchIO "4" $ Ops.composeScaling 4
]
]
, bgroup "asyncly"
[ -- benchIO "unfoldr" $ Ops.toNull asyncly
benchSrcIO asyncly "unfoldrM" Ops.sourceUnfoldrM
-- , benchSrcIO asyncly "fromFoldable" Ops.sourceFromFoldable
, benchSrcIO asyncly "fromFoldableM" Ops.sourceFromFoldableM
-- , benchSrcIO asyncly "foldMapWith" Ops.sourceFoldMapWith
, benchSrcIO asyncly "foldMapWithM" Ops.sourceFoldMapWithM
, benchIO "mapM" $ Ops.mapM asyncly
, benchSrcIO asyncly "unfoldrM maxThreads 1"
(maxThreads 1 . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM maxBuffer 1 (1000 ops)"
(maxBuffer 1 . Ops.sourceUnfoldrMN 1000)
]
, bgroup "asyncly/rate"
[ -- benchIO "unfoldr" $ Ops.toNull asyncly
benchSrcIO asyncly "unfoldrM" Ops.sourceUnfoldrM
, benchSrcIO asyncly "unfoldrM/Nothing"
(rate Nothing . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM/AvgRate/1,000,000"
(avgRate 1000000 . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM/AvgRate/3,000,000"
(avgRate 3000000 . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM/AvgRate/10,000,000/maxThreads1"
(maxThreads 1 . avgRate 10000000 . Ops.sourceUnfoldrM)
-- XXX arbitrarily large rate should be the same as rate Nothing
, benchSrcIO asyncly "unfoldrM/AvgRate/10,000,000"
(avgRate 10000000 . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM/AvgRate/20,000,000"
(avgRate 20000000 . Ops.sourceUnfoldrM)
]
, bgroup "wAsyncly"
[ -- benchIO "unfoldr" $ Ops.toNull wAsyncly
benchSrcIO wAsyncly "unfoldrM" Ops.sourceUnfoldrM
-- , benchSrcIO wAsyncly "fromFoldable" Ops.sourceFromFoldable
, benchSrcIO wAsyncly "fromFoldableM" Ops.sourceFromFoldableM
-- , benchSrcIO wAsyncly "foldMapWith" Ops.sourceFoldMapWith
, benchSrcIO wAsyncly "foldMapWithM" Ops.sourceFoldMapWithM
, benchIO "mapM" $ Ops.mapM wAsyncly
]
-- unfoldr and fromFoldable are always serial and thereofore the same for
-- all stream types.
, bgroup "aheadly"
[ -- benchIO "unfoldr" $ Ops.toNull aheadly
benchSrcIO aheadly "unfoldrM" Ops.sourceUnfoldrM
, benchSrcIO aheadly "fromFoldableM" Ops.sourceFromFoldableM
-- , benchSrcIO aheadly "foldMapWith" Ops.sourceFoldMapWith
, benchSrcIO aheadly "foldMapWithM" Ops.sourceFoldMapWithM
, benchIO "mapM" $ Ops.mapM aheadly
, benchSrcIO aheadly "unfoldrM maxThreads 1"
(maxThreads 1 . Ops.sourceUnfoldrM)
, benchSrcIO aheadly "unfoldrM maxBuffer 1 (1000 ops)"
(maxBuffer 1 . Ops.sourceUnfoldrMN 1000)
-- , benchSrcIO aheadly "fromFoldable" Ops.sourceFromFoldable
]
, bgroup "aheadly/rate"
[
-- XXX arbitrarily large maxRate should be the same as maxRate -1
benchSrcIO aheadly "unfoldrM rate AvgRate 1000000"
(avgRate 1000000 . Ops.sourceUnfoldrM)
]
-- XXX need to use smaller streams to finish in reasonable time
, bgroup "parallely"
[ --benchIO "unfoldr" $ Ops.toNull parallely
benchSrcIO parallely "unfoldrM" Ops.sourceUnfoldrM
--, benchSrcIO parallely "fromFoldable" Ops.sourceFromFoldable
, benchSrcIO parallely "fromFoldableM" Ops.sourceFromFoldableM
-- , benchSrcIO parallely "foldMapWith" Ops.sourceFoldMapWith
, benchSrcIO parallely "foldMapWithM" Ops.sourceFoldMapWithM
, benchIO "mapM" $ Ops.mapM parallely
-- Zip has only one parallel flavor
, benchIO "zip" $ Ops.zipAsync
, benchIO "zipM" $ Ops.zipAsyncM
]
]

115
benchmark/LinearAsync.hs Normal file
View File

@ -0,0 +1,115 @@
-- |
-- Module : Main
-- Copyright : (c) 2018 Harendra Kumar
--
-- License : BSD3
-- Maintainer : harendra.kumar@gmail.com
import Control.DeepSeq (NFData)
-- import Data.Functor.Identity (Identity, runIdentity)
import System.Random (randomRIO)
import qualified LinearOps as Ops
import Streamly
import Gauge
-- We need a monadic bind here to make sure that the function f does not get
-- completely optimized out by the compiler in some cases.
--
-- | Takes a fold method, and uses it with a default source.
{-# INLINE benchIO #-}
benchIO :: (IsStream t, NFData b) => String -> (t IO Int -> IO b) -> Benchmark
benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f . Ops.source
-- | Takes a source, and uses it with a default drain/fold method.
{-# INLINE benchSrcIO #-}
benchSrcIO
:: (t IO Int -> SerialT IO Int)
-> String
-> (Int -> t IO Int)
-> Benchmark
benchSrcIO t name f
= bench name $ nfIO $ randomRIO (1,1) >>= Ops.toNull t . f
{-
_benchId :: NFData b => String -> (Ops.Stream m Int -> Identity b) -> Benchmark
_benchId name f = bench name $ nf (runIdentity . f) (Ops.source 10)
-}
main :: IO ()
main = do
defaultMain
[ bgroup "asyncly"
[ -- benchIO "unfoldr" $ Ops.toNull asyncly
benchSrcIO asyncly "unfoldrM" Ops.sourceUnfoldrM
-- , benchSrcIO asyncly "fromFoldable" Ops.sourceFromFoldable
, benchSrcIO asyncly "fromFoldableM" Ops.sourceFromFoldableM
-- , benchSrcIO asyncly "foldMapWith" Ops.sourceFoldMapWith
, benchSrcIO asyncly "foldMapWithM" Ops.sourceFoldMapWithM
, benchIO "mapM" $ Ops.mapM asyncly
, benchSrcIO asyncly "unfoldrM maxThreads 1"
(maxThreads 1 . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM maxBuffer 1 (1000 ops)"
(maxBuffer 1 . Ops.sourceUnfoldrMN 1000)
]
, bgroup "asyncly/rate"
[ -- benchIO "unfoldr" $ Ops.toNull asyncly
benchSrcIO asyncly "unfoldrM" Ops.sourceUnfoldrM
, benchSrcIO asyncly "unfoldrM/Nothing"
(rate Nothing . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM/AvgRate/1,000,000"
(avgRate 1000000 . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM/AvgRate/3,000,000"
(avgRate 3000000 . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM/AvgRate/10,000,000/maxThreads1"
(maxThreads 1 . avgRate 10000000 . Ops.sourceUnfoldrM)
-- XXX arbitrarily large rate should be the same as rate Nothing
, benchSrcIO asyncly "unfoldrM/AvgRate/10,000,000"
(avgRate 10000000 . Ops.sourceUnfoldrM)
, benchSrcIO asyncly "unfoldrM/AvgRate/20,000,000"
(avgRate 20000000 . Ops.sourceUnfoldrM)
]
, bgroup "wAsyncly"
[ -- benchIO "unfoldr" $ Ops.toNull wAsyncly
benchSrcIO wAsyncly "unfoldrM" Ops.sourceUnfoldrM
-- , benchSrcIO wAsyncly "fromFoldable" Ops.sourceFromFoldable
, benchSrcIO wAsyncly "fromFoldableM" Ops.sourceFromFoldableM
-- , benchSrcIO wAsyncly "foldMapWith" Ops.sourceFoldMapWith
, benchSrcIO wAsyncly "foldMapWithM" Ops.sourceFoldMapWithM
, benchIO "mapM" $ Ops.mapM wAsyncly
]
-- unfoldr and fromFoldable are always serial and thereofore the same for
-- all stream types.
, bgroup "aheadly"
[ -- benchIO "unfoldr" $ Ops.toNull aheadly
benchSrcIO aheadly "unfoldrM" Ops.sourceUnfoldrM
, benchSrcIO aheadly "fromFoldableM" Ops.sourceFromFoldableM
-- , benchSrcIO aheadly "foldMapWith" Ops.sourceFoldMapWith
, benchSrcIO aheadly "foldMapWithM" Ops.sourceFoldMapWithM
, benchIO "mapM" $ Ops.mapM aheadly
, benchSrcIO aheadly "unfoldrM maxThreads 1"
(maxThreads 1 . Ops.sourceUnfoldrM)
, benchSrcIO aheadly "unfoldrM maxBuffer 1 (1000 ops)"
(maxBuffer 1 . Ops.sourceUnfoldrMN 1000)
-- , benchSrcIO aheadly "fromFoldable" Ops.sourceFromFoldable
]
, bgroup "aheadly/rate"
[
-- XXX arbitrarily large maxRate should be the same as maxRate -1
benchSrcIO aheadly "unfoldrM rate AvgRate 1000000"
(avgRate 1000000 . Ops.sourceUnfoldrM)
]
-- XXX need to use smaller streams to finish in reasonable time
, bgroup "parallely"
[ --benchIO "unfoldr" $ Ops.toNull parallely
benchSrcIO parallely "unfoldrM" Ops.sourceUnfoldrM
--, benchSrcIO parallely "fromFoldable" Ops.sourceFromFoldable
, benchSrcIO parallely "fromFoldableM" Ops.sourceFromFoldableM
-- , benchSrcIO parallely "foldMapWith" Ops.sourceFoldMapWith
, benchSrcIO parallely "foldMapWithM" Ops.sourceFoldMapWithM
, benchIO "mapM" $ Ops.mapM parallely
-- Zip has only one parallel flavor
, benchIO "zip" $ Ops.zipAsync
, benchIO "zipM" $ Ops.zipAsyncM
]
]

View File

@ -5,6 +5,7 @@
-- License : MIT
-- Maintainer : harendra.kumar@gmail.com
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
module LinearOps where
@ -18,8 +19,12 @@ import qualified Streamly as S
import qualified Streamly.Prelude as S
value, maxValue :: Int
#ifdef LINEAR_ASYNC
value = 10000
#else
value = 100000
maxValue = value + 1000
#endif
maxValue = value + 1
-------------------------------------------------------------------------------
-- Benchmark ops

View File

@ -1,13 +0,0 @@
module Utils where
import Control.Monad.Trans.State
import Control.Monad.Trans.Maybe
-- Like the shell "shift" to shift the command line arguments
shift :: StateT [String] (MaybeT IO) (Maybe String)
shift = do
s <- get
case s of
[] -> return Nothing
x : xs -> put xs >> return (Just x)

View File

@ -10,9 +10,9 @@ extra-deps:
- Chart-diagrams-1.9
- SVGFonts-1.6.0.3
- math-functions-0.3.0.2
- git: git@github.com:composewell/bench-graph
- git: https://github.com/composewell/bench-graph
commit: 27ea72037f01e252364197e4771e25478af97972
- git: git@github.com:harendra-kumar/statistics
- git: https://github.com/harendra-kumar/statistics
commit: d3c4743c28fdd83d578039867f1a046596f77140
subdirs:
- dense-linear-algebra

View File

@ -323,6 +323,34 @@ benchmark linear
, random >= 1.0 && < 2.0
, gauge >= 0.2.3 && < 0.3
benchmark linear-async
type: exitcode-stdio-1.0
hs-source-dirs: benchmark
main-is: LinearAsync.hs
other-modules: LinearOps
default-language: Haskell2010
ghc-options: -O2 -Wall
cpp-options: -DLINEAR_ASYNC
if flag(dev)
ghc-options: -Wmissed-specialisations
-Wall-missed-specialisations
-fno-ignore-asserts
if impl(ghc >= 8.0)
ghc-options: -Wcompat
-Wunrecognised-warning-flags
-Widentities
-Wincomplete-record-updates
-Wincomplete-uni-patterns
-Wredundant-constraints
-Wnoncanonical-monad-instances
-Wnoncanonical-monadfail-instances
build-depends:
streamly
, base >= 4.8 && < 5
, deepseq >= 1.4.0 && < 1.5
, random >= 1.0 && < 2.0
, gauge >= 0.2.3 && < 0.3
benchmark nested
type: exitcode-stdio-1.0
hs-source-dirs: benchmark
@ -410,31 +438,15 @@ benchmark base
build-depends:
semigroups >= 0.18 && < 0.19
executable chart-linear
executable chart
default-language: Haskell2010
hs-source-dirs: benchmark
main-is: ChartLinear.hs
other-modules: Utils
main-is: Chart.hs
if flag(dev)
buildable: True
build-Depends:
base >= 4.8 && < 5
, bench-graph >= 0.1 && < 0.2
, split
, transformers
else
buildable: False
executable chart-nested
default-language: Haskell2010
hs-source-dirs: benchmark
main-is: ChartNested.hs
other-modules: Utils
if flag(dev)
buildable: True
build-Depends:
base >= 4.8 && < 5
, bench-graph >= 0.1 && < 0.2
, bench-graph >= 0.2 && < 0.3
, split
, transformers
else