packages feed

fmt-0.6: bench/Main.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}

-- | Benchmarks for @fmt@ library.

module Main where

import           Control.DeepSeq         (NFData)
import           Data.Monoid             ((<>))
import           Data.String.Interpolate (i)
import           Data.Text               (Text)
import qualified Data.Text               as T
import           Fmt                     ((+|), (|+), format)
import           Formatting              (Format, formatToString, int, sformat, stext,
                                          string, (%))
import           Text.Printf             (printf)

import           Criterion               (Benchmark, bench, bgroup, nf)
import           Criterion.Main          (defaultMain)

----------------------------------------------------------------------------
-- Format utility functions
----------------------------------------------------------------------------

-- Shorter alias for @formatToString@.
fs :: Format String a -> a
fs = formatToString

tshow :: Show a => a -> Text
tshow x = T.pack (show x)

----------------------------------------------------------------------------
-- Benchmarks utility functions
----------------------------------------------------------------------------

bGenericStringGroup :: NFData s => String -> a -> [(String, a -> s)] -> Benchmark
bGenericStringGroup sTag benchObj =
    bgroup sTag . map (\(tag, howToFmt) -> bench tag (nf howToFmt benchObj))
{-# INLINE bGenericStringGroup #-}

bTextGroup :: a -> [(String, a -> Text)] -> Benchmark
bTextGroup = bGenericStringGroup "text"
{-# INLINE bTextGroup #-}

bStringGroup :: a -> [(String, a -> String)] -> Benchmark
bStringGroup = bGenericStringGroup "string"
{-# INLINE bStringGroup #-}

-- Function for convenience instead of using manual @(,)@.
taggedB :: String -> (a -> b) -> (String, a -> b)
taggedB = (,)

----------------------------------------------------------------------------
-- Benchmakrs themselves
----------------------------------------------------------------------------

main :: IO ()
main = defaultMain
  [ bgroup "simple"
    [ bTextGroup (1 :: Int, 2 :: Int)
      [ taggedB "fmt" $
          \(a,b) -> "hello "+|a|+" world "+|b|+""
      , taggedB "fmt old-style" $
          \(a,b) -> format "hello {} world {}" a b :: Text
      , taggedB "formatting" $
          \(a,b) -> sformat ("hello "%int%" world "%int) a b
      , taggedB "interpolate" $
          \(a,b) -> T.pack [i|hello #{a} world #{b}|]
      , taggedB "show" $
          \(a,b) -> "hello " <> tshow a <> " world " <> tshow b
      , taggedB "printf" $
          \(a,b) -> T.pack $ printf "hello %d world %d" a b
      ]
    , bStringGroup (1 :: Int, 2 :: Int)
      [ taggedB "fmt" $
          \(a,b) -> "hello "+|a|+" world "+|b|+""
      , taggedB "fmt old-style" $
          \(a,b) -> format "hello {} world {}" a b :: String
      , taggedB "formatting" $
          \(a,b) -> fs ("hello "%int%" world "%int) a b
      , taggedB "interpolate" $
          \(a,b) -> [i|hello #{a} world #{b}|]
      , taggedB "show" $
          \(a,b) -> "hello " ++ show a ++ " world " ++ show b
      , taggedB "printf" $
          \(a,b) -> printf "hello %d world %d" a b
      ]
    ]

  , bgroup "readme"
    [ bTextGroup (9 :: Int, "Beijing" :: Text)
      [ taggedB "fmt" $
          \(n,city) -> "There are "+|n|+" million bicycles in "+|city|+"."
      , taggedB "fmt old-style" $
          \(n,city) -> format "There are {} million bicycles in {}." n city :: Text
      , taggedB "formatting" $
          \(n,city) -> sformat ("There are "%int%" million bicycles in "%stext%".") n city
      , taggedB "interpolate" $
          \(n,city) -> T.pack [i|There are #{n} million bicycles in #{city}.|]
      , taggedB "show" $
          \(n,city) -> "There are " <> tshow n <> " million bicycles in " <> city <> "."
      , taggedB "printf" $
          \(n,city) -> T.pack $ printf "There are %d million bicycles in %s." n city
      ]
    , bStringGroup (9 :: Int, "Beijing" :: String)
      [ taggedB "fmt" $
          \(n,city) -> "There are "+|n|+" million bicycles in "+|city|+"."
      , taggedB "fmt old-style" $
          \(n,city) -> format "There are {} million bicycles in {}." n city :: String
      , taggedB "formatting" $
          \(n,city) -> fs ("There are "%int%" million bicycles in "%string%".") n city
      , taggedB "interpolate" $
          \(n,city) -> [i|There are #{n} million bicycles in #{city}.|]
      , taggedB "show" $
          \(n,city) -> "There are " ++ show n ++ " million bicycles in " ++ city ++ "."
      , taggedB "printf" $
          \(n,city) -> printf "There are %d million bicycles in %s." n city
      ]
    ]
  ]