{-# LANGUAGE TupleSections #-}
import Control.DeepSeq (NFData)
import Streamly.Data.Fold (Fold)
import Streamly.Data.Stream (Stream)
import System.Random (randomRIO)
import qualified Streamly.Data.Fold as Fold
import qualified Streamly.Data.Stream as Stream
import qualified Streamly.Data.Array as Array
import qualified Streamly.Internal.Data.Ring.Unboxed as Ring
import qualified Streamly.Statistics as Statistics
import Gauge
{-# INLINE source #-}
source :: (Monad m, Num a, Stream.Enumerable a) => Int -> a -> Stream m a
source len from =
Stream.enumerateFromThenTo from (from + 1) (from + fromIntegral len)
{-# INLINE sourceDescending #-}
sourceDescending :: (Monad m, Num a, Stream.Enumerable a) =>
Int -> a -> Stream m a
sourceDescending len from =
Stream.enumerateFromThenTo
(from + fromIntegral len)
(from + fromIntegral (len - 1))
from
{-# INLINE sourceDescendingInt #-}
sourceDescendingInt :: Monad m => Int -> Int -> Stream m Int
sourceDescendingInt = sourceDescending
{-# INLINE benchWith #-}
benchWith :: (Num a, NFData a) =>
(Int -> a -> Stream IO a) -> Int -> String -> Fold IO a a -> Benchmark
benchWith src len name f =
bench name
$ nfIO
$ randomRIO (1, 1 :: Int) >>= Stream.fold f . src len . fromIntegral
{-# INLINE benchWithFold #-}
benchWithFold :: Int -> String -> Fold IO Double Double -> Benchmark
benchWithFold len name f = benchWith source len name f
{-# INLINE benchWithFoldInt #-}
benchWithFoldInt :: Int -> String -> Fold IO Int Int -> Benchmark
benchWithFoldInt len name f = benchWith source len name f
{-# INLINE benchWithPostscan #-}
benchWithPostscan :: Int -> String -> Fold IO Double Double -> Benchmark
benchWithPostscan len name f =
bench name $ nfIO $ randomRIO (1, 1) >>=
Stream.fold Fold.drain . Stream.postscan f . source len
{-# INLINE benchWithResample #-}
benchWithResample :: Int -> String -> Benchmark
benchWithResample len name = bench name $ nfIO $ do
i <- randomRIO (1, 1)
arr <- Stream.fold Array.write (source len i :: Stream IO Double)
Stream.fold Fold.drain $ Stream.unfold Statistics.resample arr
{-# INLINE benchWithFoldResamples #-}
benchWithFoldResamples :: Int -> String -> Fold IO Double Double -> Benchmark
benchWithFoldResamples len name f = bench name $ nfIO $ do
i <- randomRIO (1, 1)
arr <- Stream.fold Array.write (source len i :: Stream IO Double)
Stream.fold Fold.drain $ Statistics.foldResamples len arr f
{-# INLINE numElements #-}
numElements :: Int
numElements = 100000
main :: IO ()
main =
defaultMain
[ bgroup
"fold"
[ benchWithFold numElements "minimum (window size 100)"
(Ring.slidingWindow 100 Statistics.minimum)
, benchWithFold numElements "minimum (window size 1000)"
(Ring.slidingWindow 1000 Statistics.minimum)
, benchWith sourceDescendingInt numElements
"minimum descending (window size 1000)"
(Ring.slidingWindow 1000 Statistics.minimum)
, benchWithFold numElements "maximum (window size 100)"
(Ring.slidingWindow 100 Statistics.maximum)
, benchWithFold numElements "maximum (window size 1000)"
(Ring.slidingWindow 1000 Statistics.maximum)
, benchWith sourceDescendingInt numElements
"maximum descending (window size 1000)"
(Ring.slidingWindow 1000 Statistics.maximum)
, benchWithFold numElements "range (window size 100)"
(Ring.slidingWindow 100 Statistics.range)
, benchWithFold numElements "range (window size 1000)"
(Ring.slidingWindow 1000 Statistics.range)
, benchWithFoldInt numElements "sumInt (window size 100)"
(Ring.slidingWindow 100 Statistics.sumInt)
, benchWithFoldInt numElements "sum for Int (window size 100)"
(Ring.slidingWindow 100 Statistics.sum)
, benchWithFold numElements "sum (window size 100)"
(Ring.slidingWindow 100 Statistics.sum)
, benchWithFold numElements "sum (window size 1000)"
(Ring.slidingWindow 1000 Statistics.sum)
, benchWithFold numElements "sum (entire stream)"
(Statistics.cumulative Statistics.sum)
, benchWithFold numElements "sum (Data.Fold)"
(Fold.sum)
, benchWithFold numElements "mean (window size 100)"
(Ring.slidingWindow 100 Statistics.mean)
, benchWithFold numElements "mean (window size 1000)"
(Ring.slidingWindow 1000 Statistics.mean)
, benchWithFold numElements "mean (entire stream)"
(Statistics.cumulative Statistics.mean)
, benchWithFold numElements "mean (Data.Fold)"
(Fold.mean)
, benchWithFold
numElements
"welfordMean (window size 100)"
(Ring.slidingWindow 100 Statistics.welfordMean)
, benchWithFold
numElements
"welfordMean (window size 1000)"
(Ring.slidingWindow 1000 Statistics.welfordMean)
, benchWithFold
numElements
"welfordMean (entire stream)"
(Statistics.cumulative Statistics.welfordMean)
, benchWithFold numElements "geometricMean (window size 100)"
(Ring.slidingWindow 100 Statistics.geometricMean)
, benchWithFold numElements "geometricMean (window size 1000)"
(Ring.slidingWindow 1000 Statistics.geometricMean)
, benchWithFold numElements "geometricMean (entire stream)"
(Statistics.cumulative Statistics.geometricMean)
, benchWithFold numElements "harmonicMean (window size 100)"
(Ring.slidingWindow 100 Statistics.harmonicMean)
, benchWithFold numElements "harmonicMean (window size 1000)"
(Ring.slidingWindow 1000 Statistics.harmonicMean)
, benchWithFold numElements "harmonicMean (entire stream)"
(Statistics.cumulative Statistics.harmonicMean)
, benchWithFold numElements "quadraticMean (window size 100)"
(Ring.slidingWindow 100 Statistics.quadraticMean)
, benchWithFold numElements "quadraticMean (window size 1000)"
(Ring.slidingWindow 1000 Statistics.quadraticMean)
, benchWithFold numElements "quadraticMean (entire stream)"
(Statistics.cumulative Statistics.quadraticMean)
, benchWithFold numElements "powerSum 2 (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerSum 2))
, benchWithFold numElements "powerSum 2 (entire stream)"
(Statistics.cumulative (Statistics.powerSum 2))
, benchWithFold numElements "rawMoment 2 (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerSum 2))
, benchWithFold numElements "rawMoment 2 (entire stream)"
(Statistics.cumulative (Statistics.rawMoment 2))
, benchWithFold numElements "powerMean 1 (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerMean 1))
, benchWithFold numElements "powerMean 2 (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerMean 2))
, benchWithFold numElements "powerMean 10 (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerMean 10))
, benchWithFold numElements "powerMeanFrac (-1) (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerMeanFrac (-1)))
, benchWithFold numElements "powerMeanFrac 1 (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerMeanFrac 1))
, benchWithFold numElements "powerMeanFrac 2 (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerMeanFrac 2))
, benchWithFold numElements "powerMeanFrac 10 (window size 100)"
(Ring.slidingWindow 100 (Statistics.powerMeanFrac 10))
, benchWithFold numElements "ewma (entire stream)"
(Statistics.ewma 0.5)
, benchWithFold numElements "ewmaAfterMean (entire stream)"
(Statistics.ewmaAfterMean 10 0.5)
, benchWithFold numElements "ewmaRampUpSmoothing (entire stream)"
(Statistics.ewmaRampUpSmoothing 0.5 0.5)
, benchWithFold numElements "variance (window size 100)"
(Ring.slidingWindow 100 (Statistics.variance))
, benchWithFold numElements "variance (entire stream)"
(Statistics.cumulative (Statistics.variance))
-- , benchWithFold numElements "variance (Data.Fold)"
-- (Fold.variance)
, benchWithFold numElements "sampleVariance (window size 100)"
(Ring.slidingWindow 100 (Statistics.sampleVariance))
, benchWithFold numElements "sampleVariance (entire stream)"
(Statistics.cumulative (Statistics.sampleVariance))
, benchWithFold numElements "stdDev (window size 100)"
(Ring.slidingWindow 100 (Statistics.stdDev))
, benchWithFold numElements "stdDev (entire stream)"
(Statistics.cumulative (Statistics.stdDev))
-- , benchWithFold numElements "stdDev (Data.Fold)"
-- (Fold.stdDev)
, benchWithFold numElements "sampleStdDev (window size 100)"
(Ring.slidingWindow 100 (Statistics.sampleStdDev))
, benchWithFold numElements "sampleStdDev (entire stream)"
(Statistics.cumulative (Statistics.sampleStdDev))
, benchWithFold numElements "stdErrMean (window size 100)"
(Ring.slidingWindow 100 (Statistics.stdErrMean))
, benchWithFold numElements "stdErrMean (entire stream)"
(Statistics.cumulative (Statistics.stdErrMean))
-- These benchmarks take a lot of time/memory with fusion-plugin possibly
-- because of the use of Tee.
#ifndef FUSION_PLUGIN
, benchWithFold numElements "skewness (window size 100)"
(Ring.slidingWindow 100 (Statistics.skewness))
, benchWithFold numElements "skewness (entire stream)"
(Statistics.cumulative (Statistics.skewness))
, benchWithFold numElements "kurtosis (window size 100)"
(Ring.slidingWindow 100 (Statistics.kurtosis))
, benchWithFold numElements "kurtosis (entire stream)"
(Statistics.cumulative (Statistics.kurtosis))
#endif
, benchWithFold numElements "md (window size 100)"
(Ring.slidingWindowWith 100 Statistics.md)
]
, bgroup
"scan"
[ benchWithPostscan numElements "minimum (window size 100)"
(Ring.slidingWindow 100 Statistics.minimum)
, benchWithPostscan numElements "minimum (window size 1000)"
(Ring.slidingWindow 1000 Statistics.minimum)
, benchWithPostscan numElements "maximum (window size 100)"
(Ring.slidingWindow 100 Statistics.maximum)
, benchWithPostscan numElements "maximum (window size 1000)"
(Ring.slidingWindow 1000 Statistics.maximum)
, benchWithPostscan numElements "range (window size 100)"
(Ring.slidingWindow 100 Statistics.range)
, benchWithPostscan numElements "range (window size 1000)"
(Ring.slidingWindow 1000 Statistics.range)
, benchWithPostscan numElements "sum (window size 100)"
(Ring.slidingWindow 100 Statistics.sum)
, benchWithPostscan numElements "sum (window size 1000)"
(Ring.slidingWindow 1000 Statistics.sum)
, benchWithPostscan numElements "mean (window size 100)"
(Ring.slidingWindow 100 Statistics.mean)
, benchWithPostscan numElements "mean (window size 1000)"
(Ring.slidingWindow 1000 Statistics.mean)
, benchWithPostscan
numElements
"welfordMean (window size 100)"
(Ring.slidingWindow 100 Statistics.welfordMean)
, benchWithPostscan
numElements
"welfordMean (window size 1000)"
(Ring.slidingWindow 1000 Statistics.welfordMean)
, benchWithPostscan
numElements
"md (window size 100)"
(Ring.slidingWindowWith 100 Statistics.md)
-- XXX These benchmarks measure the cost of creating the array as well,
-- we can do that outside the benchmark.
, benchWithResample numElements "Resample"
, benchWithFoldResamples 316 "FoldResamples 316" Fold.mean
]
]