packages feed

hpdft-0.4.6.0: scripts/bench_pages.hs

{-# LANGUAGE OverloadedStrings #-}
-- In-process benchmark: per-page interpret+layout cost on a PDF.
-- Usage: cabal exec -- ghc -O2 -package hpdft scripts/bench_pages.hs -o /tmp/bench_pages
--        /tmp/bench_pages data/sample/book.pdf
import PDF.Document (openDocument)
import PDF.Page (pageRefs)
import PDF.Interpret (interpretPageItems)
import PDF.Layout (defaultLayoutOptions, layoutPageTextWith)

import qualified Data.Text as T
import Control.Monad (forM_)
import System.Environment (getArgs)
import Data.Time.Clock (getCurrentTime, diffUTCTime)
import Text.Printf (printf)

timeIt :: IO a -> IO (Double, a)
timeIt io = do
  t0 <- getCurrentTime
  x <- io
  t1 <- getCurrentTime
  return (realToFrac (diffUTCTime t1 t0), x)

forcePage :: (Int -> Either e [item]) -> ([item] -> T.Text) -> Int -> IO Int
forcePage interp layout ref =
  case interp ref of
    Right items -> let n = T.length (layout items) in n `seq` return n
    Left _ -> return 0

main :: IO ()
main = do
  [path] <- getArgs
  doc <- openDocument path Nothing >>= either (error . show) return
  refs <- either (error . show) return (pageRefs doc)
  printf "pages: %d\n" (length refs)
  let interp = interpretPageItems doc
      layout = layoutPageTextWith defaultLayoutOptions
  -- Same heavy page repeatedly: if iterations 2+ stay slow, per-page cost
  -- is recomputed every call (no font/CMap caching across calls).
  let heavy = refs !! min 49 (length refs - 1)
  forM_ [1 .. 5 :: Int] $ \i -> do
    (t, n) <- timeIt (forcePage interp layout heavy)
    printf "page50 iter %d: %.3fs (%d chars)\n" i t n
  (ttot, _) <- timeIt $
    forM_ (zip [1 :: Int ..] refs) $ \(i, r) -> do
      (t, _) <- timeIt (forcePage interp layout r)
      if i `mod` 25 == 0 then printf "  page %3d: %.3fs\n" i t else return ()
  printf "sum of all pages (interpret+layout, per page): %.3fs\n" ttot