packages feed

document-build-0.1.0.0: bench/Main.hs

{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wall #-}

{- | Benchmarks of the pure parts of the library: composing 'FilePather' and
'Tracked' values, replacing strings, and parsing tool output.
-}
module Main (main) where

import Control.Lens (view, _Wrapped)
import Control.Monad.Reader (asks)
import Criterion.Main (bench, bgroup, defaultMain, nf, whnf)
import qualified Data.ByteString.Lazy.Char8 as Char8
import Data.Functor.Identity (Identity (..))
import qualified Data.Text as Text
import Document.Build (parsePdfinfoPages, replaceText, sha256Hex)
import System.FilePather (FilePather, Step (..), Tracked, Trail (..), step, trackedFunction, (~>))

-- | A 'FilePather' mapped over many times, to measure the fusion of 'fmap'.
mapped :: Int -> FilePather Identity Int
mapped n =
  iterate (fmap (+ 1)) (asks length) !! n

-- | A 'FilePather' piped into itself many times.
piped :: Int -> FilePather Identity FilePath
piped n =
  foldr (~>) (asks id) (replicate n (asks (<> "x")))

-- | A 'Tracked' value mapped over many times, to measure the fusion of 'fmap'.
mappedTracked :: Int -> Tracked Identity Int
mappedTracked n =
  iterate (fmap (+ 1)) (step "length" (const []) (asks length)) !! n

-- | Many steps combined with '<>', run with a trail of many steps.
combinedTracked :: Int -> Tracked Identity ()
combinedTracked n =
  foldMap (\k -> step ("step " <> show k) (\p -> [p <> "." <> show k]) (pure ())) [1 .. n]

-- | A trail of many steps.
longTrail :: Trail
longTrail =
  Trail (fmap (\k -> Step ("earlier " <> show k) ("public/" <> show k <> ".pdf")) [1 .. 100 :: Int])

-- | A flat LibreOffice document of about 1MB, with placeholders.
document :: Text.Text
document =
  Text.replicate 10000 "<text:p>Updated ${COMMIT_TIME} by ${GITLAB_USER_NAME} at revision ${CI_COMMIT_SHA}.</text:p>\n"

placeholders :: [(Text.Text, Text.Text)]
placeholders =
  [ ("${COMMIT_TIME}", "2026-10-09 01:02:03 UTC")
  , ("${GITLAB_USER_NAME}", "Tony Morris")
  , ("${CI_COMMIT_SHA}", "0123456789abcdef0123456789abcdef01234567")
  , ("${CI_PROJECT_VISIBILITY}", "public")
  ]

pdfinfo :: String
pdfinfo =
  unlines (replicate 20 "Producer:        LibreOffice" <> ["Pages:           254"])

main :: IO ()
main =
  defaultMain
    [ bgroup
        "FilePather"
        [ bench "fmap x1000" $ whnf (\n -> runIdentity (view _Wrapped (mapped n) "src/report.fodt")) 1000
        , bench "~> x1000" $ nf (\n -> runIdentity (view _Wrapped (piped n) "src/report.fodt")) 1000
        ]
    , bgroup
        "Tracked"
        [ bench "fmap x1000" $ nf (\n -> fmap snd (runIdentity (view trackedFunction (mappedTracked n) (Trail []) "src/report.fodt"))) 1000
        , bench "<> x100, trail of 100" $ nf (\n -> either (const 0) (length . fst) (runIdentity (view trackedFunction (combinedTracked n) longTrail "src/report.fodt"))) 100
        ]
    , bgroup
        "replaceText"
        [ bench "1MB, 4 placeholders" $ nf (replaceText placeholders) document
        ]
    , bgroup
        "parse"
        [ bench "parsePdfinfoPages" $ nf parsePdfinfoPages pdfinfo
        ]
    , bgroup
        "sha256Hex"
        [ bench "1MB" $ nf sha256Hex (Char8.replicate 1000000 'x')
        ]
    ]