1
+ {-# LANGUAGE ScopedTypeVariables #-}
1
2
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
2
3
{-# LANGUAGE ExistentialQuantification #-}
3
4
{-# LANGUAGE BangPatterns #-}
4
5
5
6
module Main (main ) where
6
7
7
- import Control.DeepSeq
8
- import Criterion.Measurement
9
- import Data.Function
10
- import Data.List
11
- import System.Environment
12
- import Text.CSV
8
+ import Control.DeepSeq
9
+ import Data.Function
10
+ import Data.List
11
+ import System.Environment
12
+ import Text.CSV
13
+ import Text.Printf
13
14
14
15
main :: IO ()
15
16
main = do
@@ -20,7 +21,6 @@ reportFromCsv :: FilePath -> IO ()
20
21
reportFromCsv fp = do
21
22
result <- parseCSVFromFile fp
22
23
case result of
23
- Left e -> print e
24
24
Right (_: rows) -> do
25
25
! readme <- fmap force (readFile " README.md" )
26
26
let sep = " <!-- RESULTS -->"
@@ -34,17 +34,30 @@ reportFromCsv fp = do
34
34
(filter
35
35
(not . null . filter (not . null . filter (not . null )))
36
36
(groupBy (on (==) (takeWhile (/= ' /' ) . concat . take 1 )) rows))))
37
+ _ -> error " Couldn't parse csv"
37
38
38
39
format :: [[String ]] -> String
39
40
format rows =
40
41
(" ## " ++ takeWhile (/= ' /' ) (concat (concat (take 1 (drop 1 rows))))) ++
41
42
" \n\n " ++
42
- unlines [(" |Name|" ++ intercalate " |" scales ++ " |" ), " |" ++ concat (replicate (1 + length scales) " ---|" )] ++
43
43
unlines
44
- (map (\ name -> " |" ++ name ++ " |" ++ intercalate " |" (values name) ++ " |" ) (names))
44
+ [ (" |Name|" ++ intercalate " |" scales ++ " |" )
45
+ , " |" ++ concat (replicate (1 + length scales) " ---|" )
46
+ ] ++
47
+ unlines
48
+ (map
49
+ (\ name ->
50
+ " |" ++ name ++ " |" ++ intercalate " |" (valuesByName name) ++ " |" )
51
+ (names))
45
52
where
46
- values name =
47
- map (\ (_: mean: _) -> float mean) (filter ((== name) . rowName) rows)
53
+ valuesByName name =
54
+ map
55
+ (\ row@ (_: mean: _) ->
56
+ let scale = rowScale row
57
+ in float (valuesByScale scale) (read mean))
58
+ (filter ((== name) . rowName) rows)
59
+ valuesByScale scale =
60
+ map (\ (_: mean: _) -> read mean) (filter ((== scale) . rowScale) rows)
48
61
names = nub (map rowName rows)
49
62
scales = nub (map rowScale rows)
50
63
rowName row =
@@ -57,6 +70,39 @@ format rows =
57
70
let scale = dropWhile (== ' :' ) (dropWhile (/= ' :' ) (concat (take 1 row)))
58
71
in scale
59
72
73
+ float :: [Double ] -> Double -> String
74
+ float others x = let (scale, ext) = secs (mean others)
75
+ in with (x * scale) ext
76
+
77
+ -- | Convert a number of seconds to a string. The string will consist
78
+ -- of four decimal places, followed by a short description of the time
79
+ -- units.
80
+ secs :: Double -> (Double , String )
81
+ secs k
82
+ | k >= 1 = 1 `pair` " s"
83
+ | k >= 1e-3 = 1e3 `pair` " ms"
84
+ | k >= 1e-6 = 1e6 `pair` " μs"
85
+ | k >= 1e-9 = 1e9 `pair` " ns"
86
+ | k >= 1e-12 = 1e12 `pair` " ps"
87
+ | k >= 1e-15 = 1e15 `pair` " fs"
88
+ | k >= 1e-18 = 1e18 `pair` " as"
89
+ | otherwise = error " Bad scale"
90
+ where pair= (,)
91
+
92
+ with :: Double -> String -> String
93
+ with (t :: Double ) (u :: String )
94
+ | t >= 1e9 = printf " %.4g %s" t u
95
+ | t >= 1e3 = printf " %.0f %s" t u
96
+ | t >= 1e2 = printf " %.1f %s" t u
97
+ | t >= 1e1 = printf " %.2f %s" t u
98
+ | otherwise = printf " %.3f %s" t u
60
99
61
- float :: String -> String
62
- float x = secs (read x)
100
+ -- | Simple rolling average.
101
+ mean :: [Double ] -> Double
102
+ mean =
103
+ snd .
104
+ foldr
105
+ (\ x (cnt,avg) ->
106
+ ( cnt + 1
107
+ , (x + avg * cnt) / (cnt + 1 )))
108
+ (0 , 0 )
0 commit comments