diff options
Diffstat (limited to 'src/Benchmarks/HtmlBenchmarks.hs')
-rw-r--r-- | src/Benchmarks/HtmlBenchmarks.hs | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/Benchmarks/HtmlBenchmarks.hs b/src/Benchmarks/HtmlBenchmarks.hs new file mode 100644 index 0000000..3070d52 --- /dev/null +++ b/src/Benchmarks/HtmlBenchmarks.hs | |||
@@ -0,0 +1,132 @@ | |||
1 | -- | This is a collection of HTML benchmarks for BlazeMarkup. | ||
2 | -- | ||
3 | {-# LANGUAGE OverloadedStrings, ExistentialQuantification #-} | ||
4 | {-# OPTIONS_GHC -fno-warn-unused-do-bind #-} | ||
5 | module Benchmarks.HtmlBenchmarks where | ||
6 | |||
7 | import Data.Monoid (Monoid, mempty, mconcat, mappend) | ||
8 | import Prelude hiding (div, id) | ||
9 | import qualified Prelude as P | ||
10 | |||
11 | import Benchmarks.BenchmarkUtils | ||
12 | import Text.Blaze | ||
13 | import qualified Benchmarks.BenchmarkUtils as H | ||
14 | |||
15 | -- | Description of an HTML benchmark | ||
16 | -- | ||
17 | data HtmlBenchmark = forall a. HtmlBenchmark | ||
18 | { hName :: String -- ^ Name. | ||
19 | , hR :: (a -> Html) -- ^ Rendering function. | ||
20 | , hD :: a -- ^ Data. | ||
21 | , hH :: Html } -- ^ Longer description. | ||
22 | |||
23 | -- | List containing all benchmarks. | ||
24 | -- | ||
25 | benchmarks :: [HtmlBenchmark] | ||
26 | benchmarks = | ||
27 | [ HtmlBenchmark "bigTable" bigTable bigTableData $ | ||
28 | let h = toHtml $ length bigTableData | ||
29 | w = toHtml $ length $ P.head bigTableData | ||
30 | in "Rendering of a big (" >> h >> "x" >> w >> ") HTML table" | ||
31 | , HtmlBenchmark "basic" basic basicData | ||
32 | "A simple, small basic template with a few holes to fill in" | ||
33 | , HtmlBenchmark "wideTree" wideTree wideTreeData $ | ||
34 | "A very wide tree (" >> toHtml (length wideTreeData) >> " elements)" | ||
35 | , HtmlBenchmark "wideTreeEscaping" wideTree wideTreeEscapingData $ do | ||
36 | "A very wide tree (" >> toHtml (length wideTreeData) >> " elements)" | ||
37 | " with lots of escaping" | ||
38 | , HtmlBenchmark "deepTree" deepTree deepTreeData $ do | ||
39 | "A really deep tree (" >> toHtml deepTreeData >> " nested templates)" | ||
40 | , HtmlBenchmark "manyAttributes" manyAttributes manyAttributesData $ do | ||
41 | "A single element with " >> toHtml (length manyAttributesData) | ||
42 | " attributes." | ||
43 | , HtmlBenchmark "customAttribute" customAttributes customAttributesData $ | ||
44 | "Creating custom attributes" | ||
45 | ] | ||
46 | |||
47 | rows :: Int | ||
48 | rows = 1000 | ||
49 | |||
50 | bigTableData :: [[Int]] | ||
51 | bigTableData = replicate rows [1..10] | ||
52 | {-# NOINLINE bigTableData #-} | ||
53 | |||
54 | basicData :: (String, String, [String]) | ||
55 | basicData = ("Just a test", "joe", items) | ||
56 | {-# NOINLINE basicData #-} | ||
57 | |||
58 | items :: [String] | ||
59 | items = map (("Number " `mappend`) . show) [1 :: Int .. 14] | ||
60 | {-# NOINLINE items #-} | ||
61 | |||
62 | wideTreeData :: [String] | ||
63 | wideTreeData = take 5000 $ | ||
64 | cycle ["λf.(λx.fxx)(λx.fxx)", "These old days", "Foobar", "lol", "x ∈ A"] | ||
65 | {-# NOINLINE wideTreeData #-} | ||
66 | |||
67 | wideTreeEscapingData :: [String] | ||
68 | wideTreeEscapingData = take 1000 $ | ||
69 | cycle ["<><>", "\"lol\"", "<&>", "'>>'"] | ||
70 | {-# NOINLINE wideTreeEscapingData #-} | ||
71 | |||
72 | deepTreeData :: Int | ||
73 | deepTreeData = 1000 | ||
74 | {-# NOINLINE deepTreeData #-} | ||
75 | |||
76 | manyAttributesData :: [String] | ||
77 | manyAttributesData = wideTreeData | ||
78 | |||
79 | customAttributesData :: [(String, String)] | ||
80 | customAttributesData = zip wideTreeData wideTreeData | ||
81 | |||
82 | -- | Render the argument matrix as an HTML table. | ||
83 | -- | ||
84 | bigTable :: [[Int]] -- ^ Matrix. | ||
85 | -> Html -- ^ Result. | ||
86 | bigTable t = table $ mconcat $ map row t | ||
87 | where | ||
88 | row r = tr $ mconcat $ map (td . toHtml) r | ||
89 | |||
90 | -- | Render a simple HTML page with some data. | ||
91 | -- | ||
92 | basic :: (String, String, [String]) -- ^ (Title, User, Items) | ||
93 | -> Html -- ^ Result. | ||
94 | basic (title', user, items') = html $ do | ||
95 | H.head $ title $ toHtml title' | ||
96 | body $ do | ||
97 | div ! id "header" $ (h1 $ toHtml title') | ||
98 | p $ "Hello, " `mappend` toHtml user `mappend` "!" | ||
99 | p $ "Hello, me!" | ||
100 | p $ "Hello, world!" | ||
101 | h2 $ "loop" | ||
102 | ol $ mconcat $ map (li . toHtml) items' | ||
103 | div ! id "footer" $ mempty | ||
104 | |||
105 | -- | A benchmark producing a very wide but very shallow tree. | ||
106 | -- | ||
107 | wideTree :: [String] -- ^ Text to create a tree from. | ||
108 | -> Html -- ^ Result. | ||
109 | wideTree = div . mapM_ ((p ! id "foo") . toHtml) | ||
110 | |||
111 | -- | Create a very deep tree. | ||
112 | -- | ||
113 | deepTree :: Int -- ^ Depth of the tree. | ||
114 | -> Html -- ^ Result. | ||
115 | deepTree 0 = "foo" | ||
116 | deepTree n = p $ table $ tr $ td $ div $ deepTree (n - 1) | ||
117 | |||
118 | -- | Create an element with many attributes. | ||
119 | -- | ||
120 | manyAttributes :: [String] -- ^ List of attribute values. | ||
121 | -> Html -- ^ Result. | ||
122 | manyAttributes = foldl setAttribute img | ||
123 | where | ||
124 | setAttribute html' value' = html' ! id (toValue value') | ||
125 | {-# INLINE setAttribute #-} | ||
126 | |||
127 | customAttributes :: [(String, String)] -- ^ List of attribute name, value pairs | ||
128 | -> Html -- ^ Result | ||
129 | customAttributes = foldl setAttribute img | ||
130 | where | ||
131 | setAttribute html' (name, value') = | ||
132 | html' ! customAttribute (stringTag name) (toValue value') | ||