bench 1.0.1 → 1.0.2
raw patch · 3 files changed
+106/−34 lines, 3 filesdep +optparse-applicative
Dependencies added: optparse-applicative
Files
- README.md +58/−16
- bench.cabal +7/−6
- src/Main.hs +41/−12
README.md view
@@ -1,7 +1,8 @@-# Bench v1.0.1+# Bench v1.0.2 -Think of this as a more powerful alternative to the `time` command. Use this-command-line tool to benchmark a command using Haskell's `criterion` library.+This project provides the `bench` command-line tool, which is a more powerful+alternative to the `time` command. Use `bench` to benchmark a command using+Haskell's `criterion` library. Key features: @@ -13,27 +14,26 @@ ## Quick Start -First, download the-[Haskell toolchain](https://www.haskell.org/downloads#minimal), which provides-the `stack` build tool.+You can download a pre-built binary for OS X on the releases page: -You will also need to download [git](https://git-scm.com/downloads) if you-haven't done so already.+* https://github.com/Gabriel439/bench/releases -Then run the following commands from a terminal to build and install the `bench`-tool:+... or you can install `bench` using Haskell's `stack` tool. To do that, first+download the [Haskell toolchain](https://www.haskell.org/downloads#minimal),+which provides the `stack` tool, then run: ```bash-$ git clone https://github.com/Gabriel439/bench.git-$ cd bench-$ stack install+$ stack setup+$ stack install bench ``` `stack install` will install `bench` to `~/.local/bin` or something similar. Make sure that the installation directory is on your executable search path-before running the following command. `stack` will remind you to do this if you-forget.+before running `bench`. `stack` will remind you to do this if you forget. +Once you've installed `bench` (either by download or installation via `stack`),+you can begin benchmarking programs:+ ```bash $ bench 'sleep 1' # Don't forget to quote the command line benchmarking sleep 1@@ -52,7 +52,49 @@ variance introduced by outliers: 81% (severely inflated) ``` -All output from the command being benchmarked is discarded+All output from the command being benchmarked is discarded.++Multiple commands are also supported:++```bash+$ bench id ls "sleep 0.1"+benchmarking bench/id+time 4.798 ms (4.764 ms .. 4.833 ms)+ 0.999 R² (0.998 R² .. 1.000 R²)+mean 4.909 ms (4.879 ms .. 4.953 ms)+std dev 104.6 μs (78.91 μs .. 135.7 μs)++benchmarking bench/ls+time 2.941 ms (2.889 ms .. 3.006 ms)+ 0.996 R² (0.992 R² .. 0.998 R²)+mean 3.051 ms (3.015 ms .. 3.094 ms)+std dev 129.7 μs (104.3 μs .. 178.3 μs)+variance introduced by outliers: 25% (moderately inflated)++benchmarking bench/sleep 0.1+time 109.9 ms (108.5 ms .. 111.0 ms)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 109.2 ms (108.5 ms .. 109.7 ms)+std dev 903.0 μs (676.4 μs .. 1.212 ms)+```++You can also output an HTML file graphing the distribution of+timings by using the `--output` flag:++```bash+$ bench 'ls /usr/bin | wc -l' --output example.html+benchmarking ls /usr/bin | wc -l+time 6.716 ms (6.645 ms .. 6.807 ms)+ 0.999 R² (0.999 R² .. 0.999 R²)+mean 7.005 ms (6.897 ms .. 7.251 ms)+std dev 462.0 μs (199.3 μs .. 809.2 μs)+variance introduced by outliers: 37% (moderately inflated)+```++... and if you open that page in your browser you will+get something that looks like this:++ ## Usage
bench.cabal view
@@ -1,5 +1,5 @@ name: bench-version: 1.0.1+version: 1.0.2 synopsis: Command-line benchmark tool description: Think of this as a more powerful alternative to the @time@ command. Use this command-line tool to benchmark a command@@ -25,9 +25,10 @@ hs-source-dirs: src main-is: Main.hs default-language: Haskell2010- build-depends: base >= 4.5 && < 5- , criterion >= 1.1.1.0 && < 1.2- , text < 1.3- , silently >= 1.1.1 && < 1.3- , turtle >= 1.2.5 && < 1.3+ build-depends: base >= 4.5 && < 5+ , criterion >= 1.1.1.0 && < 1.2+ , optparse-applicative >= 0.2.0 && < 0.14+ , silently >= 1.1.1 && < 1.3+ , text < 1.3+ , turtle >= 1.2.5 && < 1.3 ghc-options: -Wall -O2 -threaded
src/Main.hs view
@@ -1,34 +1,63 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-} module Main where import Control.Applicative+import Data.Monoid ((<>)) import Data.Text (Text)-import Turtle (Parser)+import Turtle (Parser, s, (%)) import qualified Criterion import qualified Criterion.Main as Criterion import qualified Criterion.Main.Options as Criterion import qualified Data.Text as Text+import qualified Options.Applicative import qualified System.IO as IO import qualified System.IO.Silently as Silently import qualified Turtle -data Options = Options- { command :: Text- , mode :: Criterion.Mode- }+version :: Text+version = "1.0.2" +data Options = Options [Text] Criterion.Mode | Version deriving (Show)+ parser :: Parser Options parser =- Options- <$> Turtle.argText "command" "The command line to benchmark"- <*> Criterion.parseWith Criterion.defaultConfig+ Version+ <$ Options.Applicative.flag'+ ()+ ( Options.Applicative.short 'v'+ <> Options.Applicative.long "version"+ <> Options.Applicative.help "Version number"+ )+ <|> Options+ <$> some+ (Turtle.argText "command(s)" "The command line(s) to benchmark")+ <*> Criterion.parseWith Criterion.defaultConfig main :: IO () main = do- o <- Turtle.options "Command-line tool to benchmark other programs" parser- let io = Turtle.shells (command o) empty+ x <- Turtle.options "Command-line tool to benchmark other programs" parser+ case x of+ Options [command] mode -> benchCommand command mode+ Options commands mode -> benchCommands commands mode+ Version -> do+ Turtle.printf ("bench version "%s%"\n") version++benchCommands :: [Text] -> Criterion.Mode -> IO ()+benchCommands commands mode = do+ let benches = map buildBench commands+ Criterion.runMode mode [Criterion.bgroup "bench" benches]++benchCommand :: Text -> Criterion.Mode -> IO ()+benchCommand command mode = do+ let bench = buildBench command+ Criterion.runMode mode [ bench ]++buildBench :: Text -> Criterion.Benchmark+buildBench command = do+ let io = Turtle.shells command empty let benchmark = Criterion.nfIO (Silently.hSilence [IO.stdout, IO.stderr] io)- let name = Text.unpack (command o)- Criterion.runMode (mode o) [ Criterion.bench name benchmark ]+ let bench = Criterion.bench (Text.unpack command) benchmark+ bench