packages feed

microbench (empty) → 0.1

raw patch · 5 files changed

+188/−0 lines, 5 filesdep +basedep +timesetup-changed

Dependencies added: base, time

Files

+ LICENSE view
@@ -0,0 +1,26 @@+Copyright (c) 2008 Evan Martin <martine@danga.com>+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 the author nor the names of 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.
+ Microbench.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE OverlappingInstances, FlexibleInstances #-}+-- microbench, a tiny microbenchmarking library for Haskell.+-- Copyright (C) 2008 Evan Martin <martine@danga.com>++-- |Microbenchmarking can be used to compare the speed of different+-- approaches to the same operation.  Since most code is very fast, to+-- get accurate timing information you must run the operation many times+-- and then divide to get the time per operation.+--+-- This library manages the microbenchmarking process: it finds how many+-- iterations of a function are needed to get a good timing estimate per+-- iteration and prints out a human-readable \"Your code takes /n/+-- nanoseconds to run, and can run /n/ times per second\".+--+-- The only function 'microbench' takes a function that expects an+-- integer parameter (which is the quantity you're trying to measure),+-- and probes the function with increasing parameters until enough time+-- has elapsed to get a good measurement.+--+-- This may be better understood by some example code:+--+-- > sum1 n = sum [1..n]+-- > sum2 n = foldl (+) 0 [1..n]+-- > main = do+-- >   microbench "Sum using sum" sum1+-- >   microbench "Sum using foldl" sum2+--+-- When run, @sum1@ and @sum2@ are called with varying values of @n@.+-- The output, then, is an estimate of how many integers these+-- approaches could sum per second.+--+-- 'microbench' also accepts a parameter of type @IO ()@ for+-- benchmarking.  It does the same probing process, but manages running+-- the operation in a loop.+module Microbench (+  microbench,+  Microbenchable+) where++import Control.Exception+import Debug.Trace+import Data.IORef+import Data.List+import Data.Time.Clock+import Data.Typeable+import Control.Concurrent+import System.IO+import Numeric++-- Want to handle:+--   Int -> a    => ok+--   Int -> IO a => ok+--   IO ()       => loop the action+-- TODO:+--   IO a  => loop the action, forcing each result?+--   a     => is it possible? I tried for a while but couldn't make it work.+--+-- TODO 2:+--   factor out "setup time" by comparing different outputs for different inputs+--   and a linear model.++-- |Microbenchmarkable computations.  Be very wary of adding your own+-- instances of this class, as it's difficult to force GHC to+-- re-evaluate code in a way that makes benchmarking easy.+class Microbenchable a where+  run :: a -> Int -> IO ()++instance Microbenchable (Int -> IO ()) where+  run f n = f n+instance Microbenchable (Int -> a) where+  run f n = do x <- evaluate (f n); return ()+instance Microbenchable (IO ()) where+  run f n = mapM_ (const f) [1..n]++-- This was chosen totally arbitrarily.  Perhaps it would be better to make it+-- a parameter, or use some sort of real statistical test.+microbenchTime = 1++-- |@microbench description target@ probes target with different parameters+-- until it's ran enough iterations to have a good estimate at the rate per+-- second of the operation.  @description@ is a textual description of the+-- thing being benchmarked.  Outputs to stdout.+microbench :: Microbenchable a => String -> a -> IO ()+microbench desc f = do+  hSetBuffering stdout NoBuffering+  putStr $ "* " ++ desc ++ ": "+  start <- getCurrentTime+  time <- probe 1+  putStrLn ""+  putStrLn $ "  " ++ showFFloat (Just 3) (time*1000*1000) "ns per iteration / "+                  ++ showGFloat (Just 2) (1 / time) " per second."+  where+  probe repeats = do+    putStr "."+    start <- getCurrentTime+    run f repeats+    end <- getCurrentTime+    let delta = end `diffUTCTime` start+    if delta > microbenchTime+      then do return (realToFrac delta / realToFrac repeats)+      else probe (repeats * 2)+
+ Setup.lhs view
@@ -0,0 +1,4 @@+#! /usr/bin/env runhaskell++> import Distribution.Simple+> main = defaultMain
+ demo.hs view
@@ -0,0 +1,29 @@+-- microbench, a tiny microbenchmarking library for Haskell.+-- Copyright (C) 2008 Evan Martin <martine@danga.com>++import Data.IORef+import Data.List (foldl')++import Microbench++b_sum, b_foldl, b_foldl' :: Int -> Int+b_sum    n = sum [1..n]+b_foldl  n = foldl (+) 0 [1..n]+b_foldl' n = foldl' (+) 0 [1..n]+b_ioref :: Int -> IO ()+b_ioref n = do+  counter <- newIORef 0+  mapM_ (\x -> modifyIORef counter (+x)) [1..n]+  readIORef counter+  return ()++main = do+  putStrLn $ "This demo benchmark measures various ways to sum a list "+          ++ "of integers."+  microbench "sum n ints" b_sum+  microbench "foldl (+) n ints" b_foldl+  microbench "foldl' (+) n ints" b_foldl'+  microbench "sum n ints with an ioref" b_ioref+  microbench "sum 1..10 with an ioref" (b_ioref 10)+  microbench "sum 1..100 with an ioref" (b_ioref 100)+  return ()
+ microbench.cabal view
@@ -0,0 +1,27 @@+Cabal-Version: >= 1.2+Name: microbench+Version: 0.1+Synopsis: Microbenchmark Haskell code+Description:+  Microbenchmarking can be used to compare the speed of different+  approaches to the same operation.  Since most code is very fast, to+  get accurate timing information you must run the operation many times+  and then divide to get the time per operation.+  .+  This library manages the microbenchmarking process: it finds how many+  iterations of a function are needed to get a good timing estimate per+  iteration and prints out a human-readable \"Your code takes /n/ nanoseconds+  to run, and can run /n/ times per second\".+Category: Development+License: BSD3+License-File: LICENSE+Author: Evan Martin+Maintainer: martine@danga.com+Copyright: (c) 2008 Evan Martin <martine@danga.com>+Homepage: http://neugierig.org/software/darcs/browse/?r=microbench;a=summary+Extra-Source-Files: demo.hs+Build-Type: Simple++Library+  Build-Depends: base, time+  Exposed-Modules: Microbench