File: Bench.hs

package info (click to toggle)
haskell-text-show 3.11.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,056 kB
  • sloc: haskell: 7,968; makefile: 6
file content (136 lines) | stat: -rw-r--r-- 4,439 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell     #-}
{-|
Module:      Bench
Copyright:   (C) 2014-2017 Ryan Scott
License:     BSD-style (see the file LICENSE)
Maintainer:  Ryan Scott
Stability:   Provisional
Portability: GHC

Benchmarks for @text-show@.
-}
module Main (main) where

import           Control.DeepSeq (NFData)

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

import qualified Data.Foldable as F
import qualified Data.Text as T

import           GHC.Generics (Generic)

import           TextShow (TextShow(..))
import           TextShow.Generic (genericShowbPrec, genericShowtPrec, genericShowtlPrec)
import           TextShow.TH (deriveTextShow)

-------------------------------------------------------------------------------
-- Tree-like ADTs
-------------------------------------------------------------------------------

-- NB: constructors must be same length!
data BinTree1 a = BTEmpty1
                | BTLeaf1 a
                | BTBranch1 (BinTree1 a) (BinTree1 a)
  deriving Show

data BinTree2 a = BTEmpty2
                | BTLeaf2 a
                | BTBranch2 (BinTree2 a) (BinTree2 a)

data BinTree3 a = BTEmpty3
                | BTLeaf3 a
                | BTBranch3 (BinTree3 a) (BinTree3 a)
  deriving Generic

instance TextShow a => TextShow (BinTree3 a) where
    showbPrec = genericShowbPrec

-------------------------------------------------------------------------------
-- Simple enumeration types
-------------------------------------------------------------------------------

data Color = Red | Green | Blue | Orange | Violet
  deriving (Generic, Show)

newtype Color2 = Color2 Color

instance TextShow Color2 where
    showbPrec  p (Color2 c) = genericShowbPrec  p c
    showtPrec  p (Color2 c) = genericShowtPrec  p c
    showtlPrec p (Color2 c) = genericShowtlPrec p c

colorShowt :: Color -> T.Text
colorShowt c = case c of
  Red    -> T.pack "Red"
  Green  -> T.pack "Green"
  Blue   -> T.pack "Blue"
  Orange -> T.pack "Orange"
  Violet -> T.pack "Violet"

-------------------------------------------------------------------------------

$(deriveTextShow ''BinTree2)
$(deriveTextShow ''Color)

-------------------------------------------------------------------------------
-- Benchmarks
-------------------------------------------------------------------------------

main :: IO ()
main = defaultMain
    [ sampleGroup "String Show"                 BTLeaf1 BTBranch1 BTEmpty1 show
    , sampleGroup "String Show, then Text.pack" BTLeaf1 BTBranch1 BTEmpty1 (T.pack . show)
    , sampleGroup "TextShow (TH)"               BTLeaf2 BTBranch2 BTEmpty2 showt
    , sampleGroup "TextShow (generics)"         BTLeaf3 BTBranch3 BTEmpty3 showt
    , bgroup "Enumeration type"
      [ bench "String Show"                 $ nf show            Violet
      , bench "String Show, then Text.pack" $ nf (T.pack . show) Violet
      , bench "TextShow (TH)"               $ nf showt           Violet
      , bench "TextShow (generics)"         $ nf showt         $ Color2 Violet
      , bench "Manually written showt"      $ nf colorShowt      Violet
      ]
    ]

sampleGroup :: forall a b. NFData b
            => String -> (Int -> a) -> (a -> a -> a) -> a -> (a -> b) -> Benchmark
sampleGroup title leaf branch empty showFun =
    bgroup title
        [ bench "Small sample"  $ nf smallSample  pile
        , bench "Medium sample" $ nf mediumSample pile
        , bench "Large sample"  $ nf largeSample  pile
        ]
  where
    pile :: (Int -> a, a -> a -> a, a, a -> b)
    pile = (leaf, branch, empty, showFun)

type Sample = forall a b.
    ( Int -> a
    , a -> a -> a
    , a
    , a -> b
    ) -> b

smallSample :: Sample
smallSample (leaf, branch, _, showFun) =
    showFun $ sampleTree leaf branch
{-# NOINLINE smallSample #-}

mediumSample :: Sample
mediumSample (leaf, branch, empty, showFun) =
    showFun . F.foldl' branch empty . replicate 1000 $ sampleTree leaf branch
{-# NOINLINE mediumSample #-}

largeSample :: Sample
largeSample (leaf, branch, empty, showFun) =
    showFun . F.foldl' branch empty . replicate 100000 $ sampleTree leaf branch
{-# NOINLINE largeSample #-}

sampleTree :: (Int -> a) -> (a -> a -> a) -> a
sampleTree leaf branch =
    (leaf 12345 `branch` leaf 1234) `branch`
    leaf 123456 `branch`
    (leaf 1234567 `branch` leaf 123456)