criterion-to-html (empty) → 0.0.0.1
raw patch · 7 files changed
+223/−0 lines, 7 filesdep +basedep +blaze-htmldep +bytestringsetup-changed
Dependencies added: base, blaze-html, bytestring, filepath
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- criterion-to-html.cabal +50/−0
- src/Criterion/ToHtml.hs +32/−0
- src/Criterion/ToHtml/Csv.hs +36/−0
- src/Criterion/ToHtml/Html.hs +38/−0
- src/Criterion/ToHtml/Result.hs +35/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, Jasper Van der Jeugt++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Jasper Van der Jeugt nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ criterion-to-html.cabal view
@@ -0,0 +1,50 @@+Name: criterion-to-html+Version: 0.0.0.1+Synopsis: Convert criterion output to HTML reports+License: BSD3+License-file: LICENSE+Author: Jasper Van der Jeugt+Maintainer: m@jaspervdj.be+Category: Development+Build-type: Simple+Homepage: http://github.com/jaspervdj/criterion-to-html+Bug-Reports: http://github.com/jaspervdj/criterion-to-html/issues+Cabal-version: >= 1.6++Description:+ A program to convert criterion output (a CSV file) to an HTML which has some+ quick and dirty plots to compare the results. To generate the CSV file, run+ your criterion benchmark using the @-u@ flag:++ .++ > some-criterion-benchmark -u results.csv++ .++ You can then convert the CSV results to some simple HTML plots using this+ program:++ .++ > criterion-to-html results.csv++ .+++Source-Repository head+ Type: git+ Location: git://github.com/jaspervdj/criterion-to-html.git++Executable criterion-to-html+ Hs-source-dirs: src/+ Main-is: Criterion/ToHtml.hs+ Build-depends:+ base >= 4 && < 5,+ blaze-html >= 0.4 && < 0.5,+ bytestring >= 0.9 && < 0.10,+ filepath >= 1.1 && < 1.3+ Other-modules:+ Criterion.ToHtml.Csv,+ Criterion.ToHtml.Html,+ Criterion.ToHtml.Result
+ src/Criterion/ToHtml.hs view
@@ -0,0 +1,32 @@+-- | Main module+--+module Main+ ( main+ ) where++import Control.Applicative ((<$>))+import System.Environment (getArgs, getProgName)+import System.FilePath (replaceExtension)++import Text.Blaze.Renderer.Utf8 (renderHtml)+import qualified Data.ByteString.Lazy as BL++import Criterion.ToHtml.Html+import Criterion.ToHtml.Result++toHtml' :: FilePath -> FilePath -> IO ()+toHtml' csv html = do+ putStrLn $ "Parsing " ++ csv+ csv' <- parseCriterionCsv <$> readFile csv+ BL.writeFile html $ renderHtml $ table csv'+ putStrLn $ "Wrote " ++ html++main :: IO ()+main = do+ args <- getArgs+ progName <- getProgName+ case args of+ [csv, html] -> toHtml' csv html+ [csv] -> toHtml' csv (replaceExtension csv "html")+ _ -> putStrLn $+ "Usage: " ++ progName ++ " <csv-file> [out-file]"
+ src/Criterion/ToHtml/Csv.hs view
@@ -0,0 +1,36 @@+-- | Simple CSV parser+--+module Criterion.ToHtml.Csv+ ( Field+ , Record+ , Csv+ , parseCsv+ ) where++type Field = String+type Record = [Field]+type Csv = [Record]++-- | Parse a CSV file+--+parseCsv :: String -> Csv+parseCsv = map parseRecord . lines++-- | Parse a CSV record+--+parseRecord :: String -> Record+parseRecord rec = case parseField rec of+ (x, ',' : y) -> x : parseRecord y+ (x, _) -> [x]++-- | Parse a CSV field+--+parseField :: String -> (Field, String)+parseField xs = case xs of+ ('"' : xs') -> parse' "" xs'+ _ -> break (== ',') xs+ where+ parse' y ('"' : '"' : ys) = parse' ('"' : y) ys+ parse' y ('"' : ys) = (reverse y, ys)+ parse' y (y' : ys) = parse' (y' : y) ys+ parse' y [] = (reverse y, "")
+ src/Criterion/ToHtml/Html.hs view
@@ -0,0 +1,38 @@+-- | Output the results to HTML+--+{-# LANGUAGE OverloadedStrings #-}+module Criterion.ToHtml.Html+ ( table+ ) where++import Data.Monoid (mappend)+import Text.Printf (printf)++import Text.Blaze (Html, toHtml, toValue, preEscapedString, (!))+import qualified Text.Blaze.Html5 as H+import qualified Text.Blaze.Html5.Attributes as A++import Criterion.ToHtml.Result++table :: [Result] -> Html+table results = H.docTypeHtml $ do+ H.head $ H.title "Criterion results"+ H.body $ do + H.table ! A.style "width: 100%;" $ do+ H.tr $ do+ H.th "Name"+ H.th "Mean"+ mapM_ row $ normalizeMeans results++row :: (Result, Double) -> Html+row (Result name _, n) = H.tr $ do+ H.td $ toHtml name+ H.td ! A.style "width: 100%" $+ H.div ! A.style (backgroundColor `mappend` "; " `mappend` width)+ $ preEscapedString " "+ where+ width = toValue $ "width: " ++ show (round (n * 100) :: Int) ++ "%"+ backgroundColor = toValue+ (printf "background-color: rgb(%d, %d, %d)" r g b :: String)+ r, g, b :: Int+ (r, g, b) = (round (150 * n), round (150 * (1 - n)), 0)
+ src/Criterion/ToHtml/Result.hs view
@@ -0,0 +1,35 @@+-- | Parse Criterion results+--+module Criterion.ToHtml.Result+ ( Result (..)+ , parseCriterionCsv+ , normalizeMeans+ ) where++import Criterion.ToHtml.Csv++-- | A criterion result+--+data Result = Result+ { resultName :: String+ , resultMean :: Double+ }++-- | Parse a Criterion CSV file+--+parseCriterionCsv :: String -> [Result]+parseCriterionCsv = map parseCriterionResult . drop 1 . parseCsv++-- | Parse a single result+--+parseCriterionResult :: Record -> Result+parseCriterionResult (name : mean : _) = Result name (read mean)+parseCriterionResult _ = error+ "Criterion.ToHtml.Parse.parseCriterionResult: invalid CSV file"++normalizeMeans :: [Result] -> [(Result, Double)]+normalizeMeans [] = []+normalizeMeans results = map normalize results+ where+ normalize result = (result, resultMean result / max')+ max' = maximum $ map resultMean results