packages feed

thyme-0.3.0.3: tests/bench.hs

import Prelude
import Control.Arrow
import Control.Applicative
import Control.Lens
import Control.Monad
import Control.Monad.IO.Class
import Criterion
import Criterion.Analysis
import Criterion.Config
import Criterion.Environment
import Criterion.Monad
import Data.Monoid
import Data.Thyme
import Data.Thyme.Calendar.OrdinalDate
import Data.Thyme.Calendar.MonthDay
import Data.Thyme.Time
import qualified Data.Time as T
import qualified Data.Time.Calendar.OrdinalDate as T
import qualified Data.Time.Calendar.WeekDate as T
import qualified Data.Time.Calendar.MonthDay as T
import qualified Data.Time.Clock.POSIX as T
import Test.QuickCheck as QC
import Test.QuickCheck.Gen as QC
import System.Locale

import System.Random
import Text.Printf

import Common

{-# ANN main "HLint: ignore Use list literal" #-}
main :: IO ()
main = do
    utcs <- unGen (vectorOf samples arbitrary) <$> newStdGen <*> pure 0
    let utcs' = review thyme <$> (utcs :: [UTCTime])
    now <- getCurrentTime
    let now' = thyme # now
    let strs = T.formatTime defaultTimeLocale spec <$> utcs'
    let dt = fromSeconds' 86405
    let dt' = thyme # dt
    let days = utctDay . unUTCTime <$> utcs
    let days' = T.utctDay <$> utcs'
    let mons = ((isLeapYear . ymdYear) &&& ymdMonth) . view gregorian <$> days
    let ords = ((isLeapYear . odYear) &&& odDay) . view ordinalDate <$> days

    let config = defaultConfig {cfgVerbosity = Last (Just Quiet)}
    (exit . and <=< withConfig config) $ do
        env <- measureEnvironment
        ns <- getConfigItem $ fromLJ cfgResamples
        mapM (benchMean env ns) $

            -- Calendar
            ( "addDays", 1.0
                , nf (addDays 28 <$>) days
                , nf (T.addDays 28 <$>) days' ) :

            ( "toOrdinalDate", 2.7
                , nf (toOrdinalDate <$>) days
                , nf (T.toOrdinalDate <$>) days' ) :

            ( "toGregorian", 4.3
                , nf (toGregorian <$>) days
                , nf (T.toGregorian <$>) days' ) :

            ( "showGregorian", 3.8
                , nf (showGregorian <$>) days
                , nf (T.showGregorian <$>) days' ) :

            ( "toWeekDate", 2.5
                , nf (toWeekDate <$>) days
                , nf (T.toWeekDate <$>) days' ) :

            ( "monthLength", 1.8
                , nf (uncurry monthLength <$>) mons
                , nf (uncurry T.monthLength <$>) mons ) :

            ( "dayOfYearToMonthAndDay", 4.3
                , nf (uncurry dayOfYearToMonthAndDay <$>) ords
                , nf (uncurry T.dayOfYearToMonthAndDay <$>) ords ) :

            -- Clock
            ( "addUTCTime", 85
                , nf (addUTCTime dt <$>) utcs
                , nf (T.addUTCTime dt' <$>) utcs' ) :

            ( "diffUTCTime", 22
                , nf (diffUTCTime now <$>) utcs
                , nf (T.diffUTCTime now' <$>) utcs' ) :

            ( "utcTimeToPOSIXSeconds", 10
                , nf (utcTimeToPOSIXSeconds <$>) utcs
                , nf (T.utcTimeToPOSIXSeconds <$>) utcs' ) :

            -- LocalTime
            ( "timeToTimeOfDay", 40
                , nf (timeToTimeOfDay <$>) (utctDayTime . unUTCTime <$> utcs)
                , nf (T.timeToTimeOfDay <$>) (T.utctDayTime <$> utcs') ) :

            ( "utcToLocalTime", 22
                , nf (utcToLocalTime utc <$>) utcs
                , nf (T.utcToLocalTime T.utc <$>) utcs' ) :

            -- Format
            ( "formatTime", 7.5
                , nf (formatTime defaultTimeLocale spec <$>) utcs
                , nf (T.formatTime defaultTimeLocale spec <$>) utcs' ) :

            ( "parseTime", 5.2
                , nf (parse <$>) strs
                , nf (parse' <$>) strs ) :

            []

  where
    samples = 32
    spec = "%F %G %V %u %j %T %s"
    parse = parseTime defaultTimeLocale spec :: String -> Maybe UTCTime
    parse' = T.parseTime defaultTimeLocale spec :: String -> Maybe T.UTCTime

    benchMean env n (name, expected, us, them) = do
        ours <- flip analyseMean n =<< runBenchmark env us
        theirs <- flip analyseMean n =<< runBenchmark env them
        let ratio = theirs / ours
        liftIO . void $ printf
            "%-23s: %6.1fns, %5.1f×; expected %4.1f× : %+3.0f%% %s\n"
            name (ours * 1000000000 / fromIntegral samples)
            ratio expected ((ratio / expected - 1) * 100)
            (if ratio >= expected then "OK." else "oh noes. D:")
        return (ratio >= expected)