packages feed

streamly-0.11.0: benchmark/Streamly/Benchmark/Data/Stream/ConcurrentThreadHeavy.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE RankNTypes #-}
-- |
-- Module      : Main
-- Copyright   : (c) 2018 Composewell Technologies
--
-- License     : BSD3
-- Maintainer  : streamly@composewell.com

import Control.Concurrent
import Control.Monad (when, replicateM)
import Streamly.Data.Stream.Prelude (Config)

import qualified Streamly.Data.Fold as Fold
import qualified Streamly.Data.Stream.Prelude as Stream

import Test.Tasty (localOption)
import Test.Tasty.Bench

-------------------------------------------------------------------------------
-- Append
-------------------------------------------------------------------------------

-- | Run @tcount@ number of actions concurrently using the given concurrency
-- style. Each thread produces a single output after a delay of @d@
-- microseconds.
--
{-# INLINE append #-}
append :: Int -> Int -> Int -> (Config -> Config) -> IO ()
append buflen tcount d modifier =
    let work i = when (d /= 0) (threadDelay d) >> return i
        cfg =
              modifier
            . Stream.maxBuffer buflen
            . Stream.maxThreads (-1)
    in Stream.fold Fold.drain
        $ Stream.parMapM cfg work
        $ Stream.fromList [1..tcount]

-- | Run @threads@ concurrently, each producing streams of @elems@ elements
-- with a delay of @d@ microseconds between successive elements, and merge
-- their outputs in a single output stream. The individual streams are produced
-- serially but merged using the provided concurrency style.
--
{-# INLINE concated #-}
concated
    :: Int
    -> Int
    -> Int
    -> Int
    -> (Config -> Config)
    -> IO ()
concated buflen threads d elems modifier =
    let work i =
            Stream.replicateM i (when (d /= 0) (threadDelay d) >> return i)
        cfg =
              modifier
            . Stream.maxBuffer buflen
            . Stream.maxThreads (-1)
    in Stream.fold Fold.drain
        $ Stream.parConcatMap cfg work
        $ Stream.replicate threads elems

appendGroup :: Int -> Int -> Int -> [Benchmark]
appendGroup buflen threads usec =
    [ -- bench "serial"   $ nfIO $ append buflen threads delay fromSerial
      bench "async"
        $ nfIO $ append buflen threads usec id
    , bench "ordered"
        $ nfIO $ append buflen threads usec (Stream.ordered True)
    , bench "interleaved"
        $ nfIO $ append buflen threads usec (Stream.interleaved True)
    , bench "parallel"
        $ nfIO $ append buflen threads usec (Stream.eager True)
    ]

concatGroup :: Int -> Int -> Int -> Int -> [Benchmark]
concatGroup buflen threads usec n =
    [ -- bench "serial"   $ nfIO $ concated buflen threads usec n serial
      bench "async"
        $ nfIO $ concated buflen threads usec n id
    , bench "ordered"
        $ nfIO $ concated buflen threads usec n (Stream.ordered True)
    , bench "interleaved"
        $ nfIO $ concated buflen threads usec n (Stream.interleaved True)
    , bench "parallel"
        $ nfIO $ concated buflen threads usec n (Stream.eager True)
    ]

main :: IO ()
main =
    defaultMain $ map (localOption (RelStDev 100000))
    [ -- bgroup "append/buf-1-threads-10k-0sec"  (appendGroup 1 10000 0)
    -- , bgroup "append/buf-100-threads-100k-0sec"  (appendGroup 100 100000 0)
      bgroup "streamly/threads10k-delay5s-singleton(buf10k)"  (appendGroup 10000 10000 5000000)
    --  bgroup "concat/buf-1-threads-100k-count-1" (concatGroup 1 100000 0 1)
    --  bgroup "concat/buf-1-threads-1-count-10m" (concatGroup 1 1 0 10000000)
    , bgroup "streamly/threads100-delay0s-stream500k(buf100)"  (concatGroup 100 100 0 500000)

    , bench "forkIO/threads10k-delay5s-singleton" $
        let delay = threadDelay 5000000
            count = 10000 :: Int
            list = [1..count]
            work i = delay >> return i
        in nfIO $ do
            ref <- newEmptyMVar
            mapM_ (\i -> forkIO (work i >>= \j -> putMVar ref j)) list
            replicateM 10000 (takeMVar ref)
   ]