diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/Microbench.hs b/Microbench.hs
new file mode 100644
--- /dev/null
+++ b/Microbench.hs
@@ -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)
+
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+#! /usr/bin/env runhaskell
+
+> import Distribution.Simple
+> main = defaultMain
diff --git a/demo.hs b/demo.hs
new file mode 100644
--- /dev/null
+++ b/demo.hs
@@ -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 ()
diff --git a/microbench.cabal b/microbench.cabal
new file mode 100644
--- /dev/null
+++ b/microbench.cabal
@@ -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
