packages feed

text-0.11.1.0: tests/benchmarks/src/Data/Text/Benchmarks/ReadNumbers.hs

-- | Read numbers from a file with a just a number on each line, find the
-- minimum of those numbers.
--
module Data.Text.Benchmarks.ReadNumbers
    ( benchmark
    ) where

import Control.Exception (evaluate)
import Criterion (Benchmark, bgroup, bench)
import Data.List (foldl')
import Numeric (readDec, readFloat, readHex)
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as BL
import qualified Data.ByteString.Lex.Double as B
import qualified Data.ByteString.Lex.Lazy.Double as BL
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import qualified Data.Text.Lazy.Read as TL
import qualified Data.Text.Read as T

benchmark :: FilePath -> IO Benchmark
benchmark fp = return $ bgroup "ReadNumbers"
    [ bench "DecimalString" $ readFile fp >>= evaluate .
        int . string readDec . lines
    , bench "HexadecimalString" $ readFile fp >>= evaluate .
        int . string readHex . lines
    , bench "DoubleString" $ readFile fp >>= evaluate .
        double . string readFloat . lines

    , bench "DecimalText" $ B.readFile fp >>= evaluate .
        int . text (T.signed T.decimal) . T.lines . T.decodeUtf8
    , bench "HexadecimalText" $ B.readFile fp >>= evaluate .
        int . text (T.signed T.hexadecimal) . T.lines . T.decodeUtf8
    , bench "DoubleText" $ B.readFile fp >>= evaluate .
        double . text T.double . T.lines . T.decodeUtf8
    , bench "RationalText" $ B.readFile fp >>= evaluate .
        double . text T.rational . T.lines . T.decodeUtf8

    , bench "DecimalLazyText" $ BL.readFile fp >>= evaluate .
        int . text (TL.signed TL.decimal) . TL.lines . TL.decodeUtf8
    , bench "HexadecimalLazyText" $ BL.readFile fp >>= evaluate .
        int . text (TL.signed TL.hexadecimal) . TL.lines . TL.decodeUtf8
    , bench "DoubleLazyText" $ BL.readFile fp >>= evaluate .
        double . text TL.double . TL.lines . TL.decodeUtf8
    , bench "RationalLazyText" $ BL.readFile fp >>= evaluate .
        double . text TL.rational . TL.lines . TL.decodeUtf8

    , bench "DecimalByteString" $ B.readFile fp >>= evaluate .
        int . byteString B.readInt . B.lines
    , bench "DoubleByteString" $ B.readFile fp >>= evaluate .
        double . byteString B.readDouble . B.lines

    , bench "DecimalLazyByteString" $ BL.readFile fp >>= evaluate .
        int . byteString BL.readInt . BL.lines
    , bench "DoubleLazyByteString" $ BL.readFile fp >>= evaluate .
        double . byteString BL.readDouble . BL.lines
    ]
  where
    -- Used for fixing types
    int :: Int -> Int
    int = id
    double :: Double -> Double
    double = id

string :: (Ord a, Num a) => (t -> [(a, t)]) -> [t] -> a
string reader = foldl' go 1000000
  where
    go z t = case reader t of [(n, _)] -> min n z
                              _        -> z

text :: (Ord a, Num a) => (t -> Either String (a,t)) -> [t] -> a
text reader = foldl' go 1000000
  where
    go z t = case reader t of Left _       -> z
                              Right (n, _) -> min n z
    
byteString :: (Ord a, Num a) => (t -> Maybe (a,t)) -> [t] -> a
byteString reader = foldl' go 1000000
  where
    go z t = case reader t of Nothing     -> z
                              Just (n, _) -> min n z