packages feed

streamly-0.8.1: benchmark/Streamly/Benchmark/Unicode/Char.hs

--
-- Module      : Streamly.Unicode.Char
-- Copyright   : (c) 2021 Composewell Technologies
-- License     : BSD-3-Clause
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC

--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------

import Control.DeepSeq (NFData)
import Streamly.Internal.Data.Array.Foreign (Array)
import System.FilePath (dropExtensions, takeFileName)
import System.FilePath.Posix ((</>))
import Gauge.Main (Benchmark, bench, bgroup, defaultMain, env, nfIO)
import Streamly.Internal.Unicode.Char
    ( NormalizationMode(NFC, NFD, NFKC, NFKD)
    , normalize
    )
import Streamly.Benchmark.Common (o_1_space_prefix)

import qualified Streamly.Internal.Data.Array.Foreign as Array
import qualified Streamly.Internal.Data.Stream.IsStream as IsStream
import qualified System.Directory as Dir

--------------------------------------------------------------------------------
-- Utilities
--------------------------------------------------------------------------------

moduleName :: String
moduleName = "Unicode.Char"

dataDir :: FilePath
dataDir = "benchmark/Streamly/Benchmark/Unicode/data"

-- Truncate or expand all datasets to this size to provide a normalized
-- measurement view across all datasets and to reduce the effect of noise
-- because of the datasets being too small.
dataSetSize :: Int
dataSetSize = 1000000

makeBench :: (NFData a) => (String, a -> IO ()) -> (String, IO a) -> Benchmark
makeBench (implName, func) (dataName, setup) =
    env setup (bench (implName ++ "/" ++ dataName) . nfIO . func)

strInput :: FilePath -> (String, IO String)
strInput file = (dataName file, fmap (take dataSetSize . cycle) (readFile file))

    where

    dataName = dropExtensions . takeFileName

arrInput :: FilePath -> (String, IO (Array Char))
arrInput file = second (fmap Array.fromList) (strInput file)

    where

    second f (a, b) = (a, f b)

--------------------------------------------------------------------------------
-- Benchmarks
--------------------------------------------------------------------------------

benchFunctions :: [(String, Array Char -> IO ())]
benchFunctions =
    [ ("NFD", IsStream.drain . normalize NFD . Array.toStream)
    , ("NFKD", IsStream.drain . normalize NFKD . Array.toStream)
    , ("NFC", IsStream.drain . normalize NFC . Array.toStream)
    , ("NFKC", IsStream.drain . normalize NFKC . Array.toStream)
    ]

main :: IO ()
main = do
    cdir <- Dir.getCurrentDirectory
    dataFiles <- fmap (dataDir </>) <$> Dir.listDirectory (cdir </> dataDir)
    defaultMain
        [ bgroup
              (o_1_space_prefix moduleName)
              (makeBench <$> benchFunctions <*> map arrInput dataFiles)
        ]