Skip to content

Instantly share code, notes, and snippets.

@erewok
Last active November 10, 2015 03:37
Show Gist options
  • Save erewok/9239cb57834789886f5c to your computer and use it in GitHub Desktop.
Save erewok/9239cb57834789886f5c to your computer and use it in GitHub Desktop.
Moving Average Test: Uses Conduits
name: conduit-test
version: 0.1.0.0
synopsis: Initial project template from stack
description: Please see README.md
homepage: https://gist.github.com/pellagic-puffbomb/9239cb57834789886f5c
license: BSD3
license-file: LICENSE
author: Erik Aker
maintainer: your.address@example.com
-- copyright:
category: Web
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
executable conduit-test
hs-source-dirs: src
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, transformers
, mtl
, conduit
, conduit-combinators
, resourcet
, containers
default-language: Haskell2010
test-suite new-template-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, conduit
, conduit-combinators
, transformers
, mtl
, resourcet
, containers
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010
source-repository head
type: git
location: https://gist.github.com/pellagic-puffbomb/9239cb57834789886f5c
{-# LANGUAGE MultiWayIf #-}
module Main where
import Control.Monad.IO.Class (liftIO)
import Data.Conduit (($$), (=$=), (=$)
, Conduit, Sink, Source
, await, yield)
import qualified Data.Conduit.List as CL
import Data.Sequence
import Prelude hiding (head, length, drop)
averageLen :: Int
averageLen = 10
type Size = Int
type RunningSum = Int
source :: Source IO Int
source = CL.sourceList [1..1000]
conduit :: RunningSum -> Size -> Seq Int -> Conduit Int IO Int
conduit total len sequence = do
val <- await
case val of
Nothing -> return ()
Just n -> do
let newtotal = total + n
let newsequence = (|>) sequence n
if | length newsequence < len -> conduit newtotal len newsequence
| length newsequence == len -> do
yield $ newtotal `div` (fromIntegral len)
conduit newtotal len newsequence
| otherwise -> do
let dropFrontTotal = fromIntegral (newtotal - index newsequence 0)
let newsequence' = drop 1 newsequence
yield $ dropFrontTotal `div` (fromIntegral len)
conduit dropFrontTotal len newsequence'
-- Using views: to be benchmarked
conduitV :: RunningSum -> Size -> Seq Int -> Conduit Int IO Int
conduitV total len sequence = do
val <- await
case val of
Nothing -> return ()
Just n -> do
let newtotal = total + n
let newsequence = (|>) sequence n
if | length newsequence < len -> conduitV newtotal len newsequence
| length newsequence == len -> do
yield $ newtotal `div` (fromIntegral len)
conduitV newtotal len newsequence
| otherwise -> do
let newSeq = viewl newsequence
case newSeq of
EmptyL -> return () -- shouldn't happen: we just appended to it above?
(a :< seq) -> do
let dropFrontTotal = newtotal - a
yield $ dropFrontTotal `div` (fromIntegral len)
conduitV dropFrontTotal len seq
sink :: Sink Int IO ()
sink = do
val <- await
case val of
Nothing -> return ()
Just n -> do
liftIO $ print n
sink
main :: IO ()
main = do
let initial = fromList []
source $$ conduitV 0 averageLen initial =$ sink
@erewok
Copy link
Author

erewok commented Nov 9, 2015

Benchmarked with criterion (whnfIO?):

Using conduit on 1..10,000

type lower bound estimate upper bound
OLS regression 51.4 ms 52.2 ms 53.0 ms
R² goodness-of-fit 0.998 0.999 1.000
Mean execution time 51.2 ms 51.7 ms 52.3 ms
Standard deviation 667 μs 954 μs 1.21 ms

Outlying measurements have slight (7.1%) effect on estimated standard deviation.

Using conduitV on 1..10,000

type lower bound estimate upper bound
OLS regression 50.9 ms 51.3 ms 51.7 ms
R² goodness-of-fit 0.998 0.999 1.000
Mean execution time 50.7 ms 51.2 ms 51.5 ms
Standard deviation 318 μs 797 μs 1.10 ms

Outlying measurements have slight (7.1%) effect on estimated standard deviation.

Using conduit on 1..100,000

type lower bound estimate upper bound
OLS regression 531 ms 540 ms 552 ms
R² goodness-of-fit 1.000 1.000 1.000
Mean execution time 538 ms 539 ms 542 ms
Standard deviation 0 s 2.01 ms 2.02 ms

Outlying measurements have moderate (18.8%) effect on estimated standard deviation.

Using conduitV on 1..100,000

type lower bound estimate upper bound
OLS regression 525 ms 528 ms 535 ms
R² goodness-of-fit 1.000 1.000 1.000
Mean execution time 527 ms 528 ms 528 ms
Standard deviation 0 s 959 μs 1.11 ms

Outlying measurements have moderate (18.7%) effect on estimated standard deviation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment