module Main where

import Control.DeepSeq
import Data.Monoid

import Criterion.Types
import Progression.Config
import Progression.Main

import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL

import qualified Data.ByteString.Builder as ByteString
import qualified Data.ByteString.Builder.Internal as ByteString

instance NFData B.ByteString

instance NFData BL.ByteString where
	rnf a = rnf (BL.toChunks a)

bytes_100 :: B.ByteString
bytes_100 = B.replicate 100 0x61

builderEmpty :: ByteString.Builder
builderEmpty = ByteString.Builder id
{-# INLINE builderEmpty #-}

builderAppend :: ByteString.Builder -> ByteString.Builder -> ByteString.Builder
builderAppend (ByteString.Builder b1) (ByteString.Builder b2) = ByteString.Builder (b1 . b2)
{-# INLINE builderAppend #-}

builderConcat :: [ByteString.Builder] -> ByteString.Builder
builderConcat = foldr builderAppend builderEmpty
{-# INLINE builderConcat #-}

build_strict :: Int -> B.ByteString
build_strict n = ByteString.toByteString builder where
	chunks = replicate n (ByteString.fromByteString bytes_100)
	builder = builderConcat chunks

build_lazy :: Int -> BL.ByteString
build_lazy n = ByteString.toLazyByteString builder where
	chunks = replicate n (ByteString.fromByteString bytes_100)
	builder = builderConcat chunks

build_strict_mconcat :: Int -> B.ByteString
build_strict_mconcat n = ByteString.toByteString builder where
	chunks = replicate n (ByteString.fromByteString bytes_100)
	builder = mconcat chunks

build_lazy_mconcat :: Int -> BL.ByteString
build_lazy_mconcat n = ByteString.toLazyByteString builder where
	chunks = replicate n (ByteString.fromByteString bytes_100)
	builder = mconcat chunks

benchmarks :: [Benchmark]
benchmarks =
	[ bench "strict" (nf build_strict 1000)
	, bench "strict +mconcat" (nf build_strict_mconcat 1000)
	, bench "lazy" (nf build_lazy 1000)
	, bench "lazy +mconcat" (nf build_lazy_mconcat 1000)
	]

main :: IO ()
main = defaultMainWith config (bgroup "all" benchmarks)

config = Config
	{ cfgMode = Nothing
	, cfgRun = RunSettings [] (Just "04_bytestring")
	, cfgGraph = mempty
	}
