packages feed

containers-benchmark (empty) → 1.0

raw patch · 40 files changed

+899/−0 lines, 40 filesdep +basedep +bytestringdep +containerssetup-changed

Dependencies added: base, bytestring, containers, criterion, random

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Milan Straka <fox@ucw.cz> 2010++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 Milan Straka <fox@ucw.cz> 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.
+ README view
@@ -0,0 +1,59 @@+This package consists of a thorough benchmark for a containers package.++Quick start+===========+To benchmark the installed version of containers, just do++cd scripts+sh benchmark.sh installed-containers none++Running+=======++The benchmark is executed using scripts in scripts directory. The main+executable is benchmark.sh, which is given several arguments:+benchmark.sh+  name_of_the_benchmark      -- date is added to it+  containers_repo            -- repo with containers, write 'none' for+                             --   system containers library+  cabal_configure_opts       -- optional flags passed to cabal configure++The benchmark.sh just calls other scripts:+  compile.sh containers_repo cabal_configure_opts   -- builds the benchmark+  run.sh name_of_the_benchmark                      -- run built benchmark+  collect.pl name_of_benchmark      -- collect all results in one .csv file++Other scripts:+  see.sh < name_of_csv              -- formats the csv file for viewing+  cmp.pl base_csv diff_csv          -- generate csv with comparison of two tests+  cmp.sh base_csv diff_csv          -- formats the result of cmp.pl for viewing++  ghc.sh containers_repo ghc_repo result_csv+    -- Compiles the GHC repo with given containers and store results+    -- the size of GHC and the memory allocation results of performance tests+    -- are stored. These tests were once a regression, so we monitor them.+    -- The GHC repo must be already booted and configured.+++Which implementation to benchmark+=================================++The benchmark can use system-installed containers package or any given repo.+Because the criterion package used for benchmarking is using containers+internally, we cannot safely expose the benchmarked implementation as+Data.Map and others. Therefore we benchmark Container.{Map,Set,IntMap,IntSet}.+The scripts/system_containers.sh and scripts/custom_containers.sh scripts+chooses which implementation of containers is benchmarked.+++Benchmark design+================++Various input data are provided by InputData/*++Various benchmark methods are provided by Benchmar/*++As the different combinations of input data and containers result in different+type signatures, we use CPP extension to put the input data and benchmark+methods into one source file and let GHC to type-check for each combination of+input data and container. This happens in Variants/*
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMain
+ containers-benchmark.cabal view
@@ -0,0 +1,68 @@+Name:                containers-benchmark+Version:             1.0+Synopsis:            Extensive benchmark suite for containers package.+Description:         This package evaluates performance of a containers package+                     from multiple perspectives.+                     .+                     It measures time and memory allocation of methods specialised+                     to several types. It can also measure the size and memory+                     allocation of GHC compiled with the containers package.+                     .+                     The containers package used can be both system-installed or+                     any darcs repository.+Homepage:            http://fox.auryn.cz/darcs/containers-benchmark/+License:             BSD3+License-file:        LICENSE+Author:              Milan Straka+Maintainer:          fox@ucw.cz+Stability:           Experimental+Category:            Benchmarking+Build-type:          Simple+Cabal-version:       >=1.2+Extra-source-files:  README+                     scripts/benchmark.sh+                     scripts/cmp.pl+                     scripts/cmp.sh+                     scripts/collect.pl+                     scripts/compile.sh+                     scripts/custom_containers.sh+                     scripts/ghc.sh+                     scripts/run.sh+                     scripts/see.sh+                     scripts/system_containers.sh+                     src/Driver.inc.hs+                     src/Benchmark/Map-like.inc.hs+                     src/Benchmark/Set-like.inc.hs+                     src/Variants/gen.sh++Executable benchmark+  Main-is:           Main.hs+  Build-depends:     base >= 3 && < 5,+                     bytestring >= 0.9 && < 1.0,+                     containers >= 0.3 && < 0.5,+                     criterion >= 0.5 && < 0.6,+                     random >= 1.0 && < 1.1+  Hs-source-dirs:    src+  Other-modules:     Container.IntMap+                     Container.IntSet+                     Container.Map+                     Container.Set+                     InputData.ByteString+                     InputData.Int+                     InputData.IntegerBig+                     InputData.IntegerSmall+                     InputData.String+                     Variants.IntMap_Int+                     Variants.IntSet_Int+                     Variants.Map_ByteString+                     Variants.Map_Int+                     Variants.Map_IntegerBig+                     Variants.Map_IntegerSmall+                     Variants.Map_String+                     Variants.Set_ByteString+                     Variants.Set_Int+                     Variants.Set_IntegerBig+                     Variants.Set_IntegerSmall+                     Variants.Set_String+  if impl(ghc >= 7.0)+    Ghc-Options: -rtsopts
+ scripts/benchmark.sh view
@@ -0,0 +1,13 @@+#!/bin/sh++[ -n "$1" ] || { echo Missing name of the benchmark run!; exit 1; }+[ -n "$2" ] || { echo Missing name of the containers repo or \'none\'!; exit 1; }++dir="$1-`date +%y%m%d`"+[ -d "$dir" ] || mkdir "$dir"+repo="$2"+shift 2++sh compile.sh "$repo" "$@"+sh run.sh "$dir"+perl collect.pl "$dir"
+ scripts/cmp.pl view
@@ -0,0 +1,69 @@+#!/usr/bin/perl+use strict;+use warnings;++sub usage() {+  print "Usage: $0 original.csv new.csv";+  exit 1;+}++-f "$ARGV[0]" or usage();+-f "$ARGV[1]" or usage();++open (my $fori, "<", $ARGV[0]) or die "Cannot open $ARGV[0]!";+open (my $fnew, "<", $ARGV[1]) or die "Cannot open $ARGV[1]!";++my @totals;+sub print_totals() {+  for my $mean ("geo", "ari") {+    print "total ($mean mean)";+    for my $i (1..$#totals) {+      print ";";+      next unless @{$totals[$i]};+      my $avg;+      if ($mean eq "geo" ) {+        $avg = 1.0;+        foreach my $v (@{$totals[$i]}) { $avg *= $v; }+        $avg **= 1/@{$totals[$i]};+      } elsif ($mean eq "ari") {+        $avg = 0.0;+        foreach my $v (@{$totals[$i]}) { $avg += $v; }+        $avg /= @{$totals[$i]};+      }+      printf "%.1f%%", 100 * $avg - 100;+    }+    print "\n";+  }+  @totals = ();+}++my ($lori, $lnew);+while ($lori = <$fori> and $lnew = <$fnew>) {+  chomp($lori);+  chomp($lnew);++  my @cori = split /;/, $lori;+  my @cnew = split /;/, $lnew;++  die "Nonequal number of columns on line $.!" if scalar(@cori) != scalar(@cnew);++  for my $i (0..$#cori) {+    my ($ori, $new) = ($cori[$i], $cnew[$i]);+    die "Empty versus nonempty column $i on line $.!" if length($ori) > 0 && length($new) == 0;+    die "Empty versus nonempty column $i on line $.!" if length($ori) == 0 && length($new) > 0;++    print ";" if $i > 0;+    if ($ori =~ /^[0-9.e+-]+$/ && $new =~ /^[0-9.e+-]+$/) {+      printf "%.1f%%", 100 * $new / $ori - 100;+      $totals[$i] = [] unless defined $totals[$i];+      push @{$totals[$i]}, $new / $ori;+    } elsif ($ori ne $new) {+      die "Different nonnumeric column $i on line $., '$ori' vs '$new'!";+    } else {+      print $ori;+    }+  }+  print_totals unless @cori;+  print "\n";+}+print_totals if @totals;
+ scripts/cmp.sh view
@@ -0,0 +1,3 @@+#!/bin/sh++perl ${0%cmp.sh}cmp.pl "$1" "$2" | column -nts\; | less -S
+ scripts/collect.pl view
@@ -0,0 +1,75 @@+#!/usr/bin/perl+use strict;+use warnings;++-d $ARGV[0] or die "Missing name of directory to collect!";++sub read_csv($) {+  chomp(my $line = $_[0]);+  $line =~ /^"?([^,"]*)"?,([^,]*)(,|$)/ or die "Bad line $line!";+  return ($1, $2);+}++my %tests;+my %variants;++# Read individual results+foreach my $csv (glob "$ARGV[0]/*[!m].csv") {+  # Read time+  $csv =~ m#/([^/]*)_[0-9]*m?.csv$# or die "Bad csv filename $csv!";+  my $variant = $1;+  $variants{$variant} = 1;+  open(my $f,"<", $csv) or die "Cannot open file $csv!";+  my $_header = <$f>;+  foreach my $line (<$f>) {+    my ($name, $res) = read_csv($line);+    $tests{$name} = {} unless exists $tests{$name};+    exists $tests{$name}->{$variant} and die "Repeated data $name-$variant!";+    $tests{$name}->{$variant} = [$res];+  }+  close($f);++  # Read memory+  $csv =~ s#\.csv$#m.csv# or die "Bad csv filenaem $csv!";+  open($f,"<", $csv) or die "Cannot open file $csv!";+  $_header = <$f>;+  foreach my $line (<$f>) {+    my ($name, $res) = read_csv($line);+    length @{$tests{$name}->{$variant}} == 1 or die "Repeated data $name-$variant!";+    push @{$tests{$name}->{$variant}}, $res;+  }+  close($f);+}++# Write merged csv+open (my $f, ">", "$ARGV[0].csv") or die "Cannot open $ARGV[0].csv!";+print $f ";";+foreach my $v (sort keys %variants) {+  print $f "$v;;";+}+print $f "\n";++foreach my $test (sort keys %tests) {+  print $f "$test;";+  foreach my $v (sort keys %variants) {+    if (exists $tests{$test}->{$v}) {+      print $f "$tests{$test}->{$v}->[0];$tests{$test}->{$v}->[1];";+    } else {+      print $f ";;";+    }+  }+  print $f "\n";+}++# Write sizes of benchmark and modules.+print $f "\nFile;Size\n";+foreach my $n ("../dist/build/benchmark/benchmark",+               "../dist/build/benchmark/benchmark-tmp/Container/Map.o",+               "../dist/build/benchmark/benchmark-tmp/Container/Set.o",+               "../dist/build/benchmark/benchmark-tmp/Container/IntMap.o",+               "../dist/build/benchmark/benchmark-tmp/Container/IntSet.o") {+  $n =~ m#/([^/]*)$#;+  print $f "$1;" . (-s $n) . "\n";+}++close($f);
+ scripts/compile.sh view
@@ -0,0 +1,13 @@+#!/bin/sh++if [ "$1" = none ]+then+  echo Using default containers+  sh system_containers.sh+else+  echo Using containers from $1+  sh custom_containers.sh $1 || { echo Containers repo not found in $1; exit 1; }+fi+shift++(cd .. && cabal clean && cabal configure "$@" && cabal build && strip dist/build/benchmark/benchmark )
+ scripts/custom_containers.sh view
@@ -0,0 +1,23 @@+#!/bin/sh++# This package _manually_ sets options for the containers+# repo used. We could extract the options from cabal file+# of from setup-config created by cabal configure.++set -e++FLAGS=-O2+if grep -q '0\.3\.0\.0' $1/containers.cabal+then+  FLAGS="$FLAGS -cpp -XMagicHash"+else+  FLAGS="$FLAGS -fregs-graph"+fi++for c in Map Set IntMap IntSet+do+  cat "$1/Data/$c.hs" | sed '+    1i {-# OPTIONS_GHC '"$FLAGS"' #-}+    s/Data\.\(IntMap\|IntSet\|Map\|Set\)/Container.\1/+  ' >../src/Container/$c.hs+done
+ scripts/ghc.sh view
@@ -0,0 +1,38 @@+#!/bin.sh++set -e++function usage {+  echo Usage: ghc.sh containers_repo ghc_repo result.csv+}++[ -d "$1" ] || { usage; exit 1; }+[ -d "$2" ] || { usage; exit 1; }+[ -n "$3" ] || { usage; exit 1; }++# 1) get ready the GHC source tree+cp "$1/containers.cabal" "$2/libraries/containers/"+cp "$1/Data/IntMap.hs"   "$2/libraries/containers/Data/"+cp "$1/Data/IntSet.hs"   "$2/libraries/containers/Data/"+cp "$1/Data/Map.hs"      "$2/libraries/containers/Data/"+cp "$1/Data/Set.hs"      "$2/libraries/containers/Data/"++# 2) build GHC+(cd "$2" && make -j4)++# 3) collect the results+> "$3"+echo "File;Size" > "$3"+stat -c "ghc-stage2;%s" "$2/inplace/lib/ghc-stage2" >> "$3"+cp "$2/inplace/lib/ghc-stage2" /tmp/ghc-stage2+strip /tmp/ghc-stage2+stat -c "ghc-stage2 (stripped);%s" /tmp/ghc-stage2 >> "$3"+rm /tmp/ghc-stage2++echo -e "\nTest;Bytes allocated" >> "$3"+(cd "$2/testsuite/tests/ghc-regress/perf/compiler/" && make)+for t in T1969 T3294+do+  echo -n "$t;" >> "$3"+  sed -n 's/^.*bytes allocated.*"\([0-9]*\)".*$/\1/;T;p' "$2/testsuite/tests/ghc-regress/perf/compiler/$t.comp.stats" >> "$3"+done
+ scripts/run.sh view
@@ -0,0 +1,42 @@+#!/bin/sh++[ -f "../dist/build/benchmark/benchmark" ] || { echo Compile the benchmark first!; exit 1; }+[ -n "$1" ] || { echo Missing name of the benchmark run!; exit 1; }++[ -d "$1" ] || mkdir "$1"++for c in IntMap IntSet Map Set+do+   for b in "Int " "IntegerSmall " "IntegerBig " "String 8" "String 50" "ByteString 8" "ByteString 50"+   do+     [ "$c" = IntMap -o "$c" = IntSet ] && [ "$b" != "Int " ] && continue++     for l in 1000 50000+     do+       (+       csv="$1/${c}_${b% *}${b#* }_$l.csv"+       csvm="${csv%.csv}m.csv"++       # Time benchmarks+       ../dist/build/benchmark/benchmark ${c}_$b $l -s 25 -g -u "$csv"++       # Memory benchmarks+       benchs=`tail -n+2 $csv | cut -d, -f1 | tr -d \"`+       case $b in+         Int*) repetitions=`expr 500000 / $l`;;+         *String*8) repetitions=`expr 100000 / $l`;;+         *String*50) repetitions=`expr 50000 / $l`;;+       esac++       head -1 "$csv" > "$csvm"+       for bench in $benchs+       do+         echo -n \"$bench\", >> "$csvm"+         ../dist/build/benchmark/benchmark ${c}_$b $l raw $bench $repetitions +RTS -t 2>&1 | sed -n "s/^.*ghc: \([0-9]*\) bytes.*$/\1/p" >> "$csvm"+       done+       ) &+     done+     wait++   done+done
+ scripts/see.sh view
@@ -0,0 +1,15 @@+#!/bin/sh++perl -pe '+  @res = ();+  foreach $p (split /;/) {+    if ($p > 0 && $p < 1000) {+      push @res, sprintf("%.1e", $p);+    } elsif ($p >= 1000) {+      push @res, sprintf("%.0fMB", $p >> 20);+    } else {+      push @res, $p;+    }+  }+  $_ = join ";", @res;+' | column -nts\; | less -S
+ scripts/system_containers.sh view
@@ -0,0 +1,10 @@+#!/bin/sh++for c in Map Set IntMap IntSet+do+  cat >../src/Container/$c.hs <<EOF+module Container.$c (module Data.$c) where++import Data.$c+EOF+done
+ src/Benchmark/Map-like.inc.hs view
@@ -0,0 +1,58 @@+create list = C.fromList (zip list list)+benchs = [ ("insert", bench_insert)+         , ("lookup0", bench_lookup0)+         , ("lookup50", bench_lookup50)+         , ("lookup100", bench_lookup100)+         , ("delete", bench_delete)+         , ("alter-insert", bench_alterinsert)+         , ("alter-delete", bench_alterdelete)+         , ("union", bench_union)+         , ("difference", bench_difference)+         , ("intersection", bench_intersection)+         , ("fold-list", bench_foldlist)+#ifdef FOLD_SUM+         , ("fold-sum", bench_foldsum)+#endif+         ]++bench_insert (list, _, _, _) = go C.empty list+  where go !c [] = ()+        go !c (x:xs) = go (C.insert x x c) xs++bench_lookup100 (list, c, _, _) = go c list+  where go c [] = ()+        go c (x:xs) = C.lookup x c `seq` go c xs++bench_lookup50 (list, _, _, c_odd) = go c_odd list+  where go c [] = ()+        go c (x:xs) = C.lookup x c `seq` go c xs++bench_lookup0 (list, _, _, c_odd) = go c_odd list+  where go c [] = ()+        go c [_] = ()+        go c (_:x:xs) = C.lookup x c `seq` go c xs++bench_delete (list, c, _, _) = go c list+  where go !c [] = ()+        go !c (x:xs) = go (C.delete x c) xs++bench_alterinsert (list, _, _, _) = go C.empty list+  where go !c [] = ()+        go !c (x:xs) = go (C.alter (const $ Just x) x c) xs++bench_alterdelete (list, c, _, _) = go c list+  where go !c [] = ()+        go !c (x:xs) = go (C.alter (const $ Nothing) x c) xs++bench_union (_, _, c_even, c_odd) = C.union c_even c_odd `seq` ()++bench_difference (_, c, c_even, _) = C.difference c c_even `seq` ()++bench_intersection (_, c, c_even, _) = C.intersection c c_even `seq` ()++bench_foldlist (_, c, _, _) = force $ C.fold (:) [] c+  where force list = length list `seq` ()++#ifdef FOLD_SUM+bench_foldsum (_, c, _, _) = C.fold (+) 0 c `seq` ()+#endif
+ src/Benchmark/Set-like.inc.hs view
@@ -0,0 +1,48 @@+create list = C.fromList list+benchs = [ ("insert", bench_insert)+         , ("member0", bench_member0)+         , ("member50", bench_member50)+         , ("member100", bench_member100)+         , ("delete", bench_delete)+         , ("union", bench_union)+         , ("difference", bench_difference)+         , ("intersection", bench_intersection)+         , ("fold-list", bench_foldlist)+#ifdef FOLD_SUM+         , ("fold-sum", bench_foldsum)+#endif+         ]++bench_insert (list, _, _, _) = go C.empty list+  where go !c [] = ()+        go !c (x:xs) = go (C.insert x c) xs++bench_member100 (list, c, _, _) = go c list+  where go c [] = ()+        go c (x:xs) = C.member x c `seq` go c xs++bench_member50 (list, _, _, c_odd) = go c_odd list+  where go c [] = ()+        go c (x:xs) = C.member x c `seq` go c xs++bench_member0 (list, _, _, c_odd) = go c_odd list+  where go c [] = ()+        go c [_] = ()+        go c (_:x:xs) = C.member x c `seq` go c xs++bench_delete (list, c, _, _) = go c list+  where go !c [] = ()+        go !c (x:xs) = go (C.delete x c) xs++bench_union (_, _, c_even, c_odd) = C.union c_even c_odd `seq` ()++bench_difference (_, c, c_even, _) = C.difference c c_even `seq` ()++bench_intersection (_, c, c_even, _) = C.intersection c c_even `seq` ()++bench_foldlist (_, c, _, _) = force $ C.fold (:) [] c+  where force list = length list `seq` ()++#ifdef FOLD_SUM+bench_foldsum (_, c, _, _) = C.fold (+) 0 c `seq` ()+#endif
+ src/Container/IntMap.hs view
@@ -0,0 +1,3 @@+module Container.IntMap (module Data.IntMap) where++import Data.IntMap
+ src/Container/IntSet.hs view
@@ -0,0 +1,3 @@+module Container.IntSet (module Data.IntSet) where++import Data.IntSet
+ src/Container/Map.hs view
@@ -0,0 +1,3 @@+module Container.Map (module Data.Map) where++import Data.Map
+ src/Container/Set.hs view
@@ -0,0 +1,3 @@+module Container.Set (module Data.Set) where++import Data.Set
+ src/Driver.inc.hs view
@@ -0,0 +1,40 @@+import Criterion.Main (bench, defaultMain, whnf)+import System.Environment (getArgs, withArgs)++bench_criterion benchs =+  defaultMain $ map (\(name, method, input) -> bench name (whnf method input)) benchs++bench_raw benchs = do+  bencharg : numreparg : _ <- getArgs+  let [(_, method, input)] = filter (\(name, _, _) -> name == bencharg) benchs+      numrep = read numreparg+  go numrep method input++ where+  go !0 _      _     = return ()+  go !n method input = method input `seq` go (n-1) method input++driver asc rnd = do+  lenarg : args <- getArgs++  let len = read lenarg+      asc_list = asc len+      asc_data = (asc_list, create asc_list, create (even asc_list), create (odd asc_list))+      rnd_list = rnd len+      rnd_data = (rnd_list, create rnd_list, create (even rnd_list), create (odd rnd_list))+      benchs' = concatMap ( \(name, method) -> [(name ++ "_asc" ++ lenarg, method, asc_data),+                                                (name ++ "_rnd" ++ lenarg, method, rnd_data)]+                          ) benchs++  case args of+    "raw" : args' -> withArgs args' $ bench_raw benchs'+    args'         -> withArgs args' $ bench_criterion benchs'++ where+  even []       = []+  even [_]      = []+  even (_:x:xs) = x : even xs++  odd []       = []+  odd [x]      = [x]+  odd (x:_:xs) = x : odd xs
+ src/InputData/ByteString.hs view
@@ -0,0 +1,11 @@+module InputData.ByteString ( asc+                            , rnd+                            ) where+import Data.ByteString.Char8 (ByteString, pack)+import qualified InputData.String++asc :: Int -> Int -> [ByteString]+asc strlen num = map pack $ InputData.String.asc strlen num++rnd :: Int -> Int -> [ByteString]+rnd strlen num = map pack $ InputData.String.rnd strlen num
+ src/InputData/Int.hs view
@@ -0,0 +1,10 @@+module InputData.Int ( asc+                     , rnd+                     ) where+import System.Random (mkStdGen, randomRs)++asc :: Int -> [Int]+asc len = [1..len]++rnd :: Int -> [Int]+rnd len = take len $ randomRs (0,1000 * len) $ mkStdGen 1234
+ src/InputData/IntegerBig.hs view
@@ -0,0 +1,10 @@+module InputData.IntegerBig ( asc+                            , rnd+                            ) where+import System.Random (mkStdGen, randomRs)++asc :: Int -> [Integer]+asc len = [0, 2^64 .. 2^64 * (fromIntegral len - 1)]++rnd :: Int -> [Integer]+rnd len = take len $ randomRs (0, 1000 * 2^64 * (fromIntegral len - 1)) $ mkStdGen 1234
+ src/InputData/IntegerSmall.hs view
@@ -0,0 +1,10 @@+module InputData.IntegerSmall ( asc+                              , rnd+                              ) where+import System.Random (mkStdGen, randomRs)++asc :: Int -> [Integer]+asc len = [1..fromIntegral len]++rnd :: Int -> [Integer]+rnd len = take len $ randomRs (0,1000 * fromIntegral len) $ mkStdGen 1234
+ src/InputData/String.hs view
@@ -0,0 +1,16 @@+module InputData.String ( asc+                        , rnd+                        ) where+import System.Random (mkStdGen, randomRs)++asc :: Int -> Int -> [String]+asc strlen num = take num $ iterate (snd . inc) $ replicate strlen 'a'+  where inc [] = (True, [])+        inc (c:cs) = case inc cs of (True, cs') | c == 'z'  -> (True, 'a' : cs')+                                                | otherwise -> (False, succ c : cs')+                                    (False, cs')            -> (False, c : cs')++rnd :: Int -> Int -> [String]+rnd strlen num = take num $ split $ randomRs ('a', 'z') $ mkStdGen 1234+  where+    split cs = case splitAt strlen cs of (str, cs') -> str : split cs'
+ src/Main.hs view
@@ -0,0 +1,33 @@+module Main where++import System.Environment (getArgs, withArgs)++import qualified Variants.IntMap_Int as IM_I+import qualified Variants.IntSet_Int as IS_I+import qualified Variants.Map_ByteString as M_BS+import qualified Variants.Map_IntegerBig as M_IB+import qualified Variants.Map_IntegerSmall as M_IS+import qualified Variants.Map_Int as M_I+import qualified Variants.Map_String as M_S+import qualified Variants.Set_ByteString as S_BS+import qualified Variants.Set_IntegerBig as S_IB+import qualified Variants.Set_IntegerSmall as S_IS+import qualified Variants.Set_Int as S_I+import qualified Variants.Set_String as S_S++main = do+  variant : args <- getArgs+  withArgs args $+    case variant of+      "IntMap_Int"       -> IM_I.benchmark+      "IntSet_Int"       -> IS_I.benchmark+      "Map_ByteString"   -> M_BS.benchmark+      "Map_IntegerBig"   -> M_IB.benchmark+      "Map_IntegerSmall" -> M_IS.benchmark+      "Map_Int"          -> M_I.benchmark+      "Map_String"       -> M_S.benchmark+      "Set_ByteString"   -> S_BS.benchmark+      "Set_IntegerBig"   -> S_IB.benchmark+      "Set_IntegerSmall" -> S_IS.benchmark+      "Set_Int"          -> S_I.benchmark+      "Set_String"       -> S_S.benchmark
+ src/Variants/IntMap_Int.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.IntMap_Int ( benchmark ) where++import qualified Container.IntMap as C+import qualified InputData.Int+#include "../Driver.inc.hs"++#define FOLD_SUM+#include "../Benchmark/Map-like.inc.hs"++benchmark = driver (InputData.Int.asc) (InputData.Int.rnd)
+ src/Variants/IntSet_Int.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.IntSet_Int ( benchmark ) where++import qualified Container.IntSet as C+import qualified InputData.Int+#include "../Driver.inc.hs"++#define FOLD_SUM+#include "../Benchmark/Set-like.inc.hs"++benchmark = driver (InputData.Int.asc) (InputData.Int.rnd)
+ src/Variants/Map_ByteString.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Map_ByteString ( benchmark ) where++import qualified Container.Map as C+import qualified InputData.ByteString+#include "../Driver.inc.hs"++#include "../Benchmark/Map-like.inc.hs"++benchmark = do+  strlenarg : args <- getArgs+  let strlen = read strlenarg+  withArgs args $ driver (InputData.ByteString.asc strlen) (InputData.ByteString.rnd strlen)
+ src/Variants/Map_Int.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Map_Int ( benchmark ) where++import qualified Container.Map as C+import qualified InputData.Int+#include "../Driver.inc.hs"++#define FOLD_SUM+#include "../Benchmark/Map-like.inc.hs"++benchmark = driver (InputData.Int.asc) (InputData.Int.rnd)
+ src/Variants/Map_IntegerBig.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Map_IntegerBig ( benchmark ) where++import qualified Container.Map as C+import qualified InputData.IntegerBig+#include "../Driver.inc.hs"++#define FOLD_SUM+#include "../Benchmark/Map-like.inc.hs"++benchmark = driver (InputData.IntegerBig.asc) (InputData.IntegerBig.rnd)
+ src/Variants/Map_IntegerSmall.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Map_IntegerSmall ( benchmark ) where++import qualified Container.Map as C+import qualified InputData.IntegerSmall+#include "../Driver.inc.hs"++#define FOLD_SUM+#include "../Benchmark/Map-like.inc.hs"++benchmark = driver (InputData.IntegerSmall.asc) (InputData.IntegerSmall.rnd)
+ src/Variants/Map_String.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Map_String ( benchmark ) where++import qualified Container.Map as C+import qualified InputData.String+#include "../Driver.inc.hs"++#include "../Benchmark/Map-like.inc.hs"++benchmark = do+  strlenarg : args <- getArgs+  let strlen = read strlenarg+  withArgs args $ driver (InputData.String.asc strlen) (InputData.String.rnd strlen)
+ src/Variants/Set_ByteString.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Set_ByteString ( benchmark ) where++import qualified Container.Set as C+import qualified InputData.ByteString+#include "../Driver.inc.hs"++#include "../Benchmark/Set-like.inc.hs"++benchmark = do+  strlenarg : args <- getArgs+  let strlen = read strlenarg+  withArgs args $ driver (InputData.ByteString.asc strlen) (InputData.ByteString.rnd strlen)
+ src/Variants/Set_Int.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Set_Int ( benchmark ) where++import qualified Container.Set as C+import qualified InputData.Int+#include "../Driver.inc.hs"++#define FOLD_SUM+#include "../Benchmark/Set-like.inc.hs"++benchmark = driver (InputData.Int.asc) (InputData.Int.rnd)
+ src/Variants/Set_IntegerBig.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Set_IntegerBig ( benchmark ) where++import qualified Container.Set as C+import qualified InputData.IntegerBig+#include "../Driver.inc.hs"++#define FOLD_SUM+#include "../Benchmark/Set-like.inc.hs"++benchmark = driver (InputData.IntegerBig.asc) (InputData.IntegerBig.rnd)
+ src/Variants/Set_IntegerSmall.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Set_IntegerSmall ( benchmark ) where++import qualified Container.Set as C+import qualified InputData.IntegerSmall+#include "../Driver.inc.hs"++#define FOLD_SUM+#include "../Benchmark/Set-like.inc.hs"++benchmark = driver (InputData.IntegerSmall.asc) (InputData.IntegerSmall.rnd)
+ src/Variants/Set_String.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.Set_String ( benchmark ) where++import qualified Container.Set as C+import qualified InputData.String+#include "../Driver.inc.hs"++#include "../Benchmark/Set-like.inc.hs"++benchmark = do+  strlenarg : args <- getArgs+  let strlen = read strlenarg+  withArgs args $ driver (InputData.String.asc strlen) (InputData.String.rnd strlen)
+ src/Variants/gen.sh view
@@ -0,0 +1,38 @@+#!/bin/sh++for c in Map Set IntMap IntSet+do+  for i in Int IntegerSmall IntegerBig String ByteString+  do+    [ "$c" = IntMap -o "$c" = IntSet ] && [ "$i" != Int ] && continue++    case $i in+      Int | IntegerSmall | IntegerBig)+        addons="+#define FOLD_SUM";+        benchmark="+benchmark = driver (InputData.$i.asc) (InputData.$i.rnd)";;++      String | ByteString)+        addons="";+        benchmark="+benchmark = do+  strlenarg : args <- getArgs+  let strlen = read strlenarg+  withArgs args $ driver (InputData.$i.asc strlen) (InputData.$i.rnd strlen)";;+    esac++    cat >${c}_$i.hs <<EOF+{-# LANGUAGE CPP, BangPatterns #-}++module Variants.${c}_$i ( benchmark ) where++import qualified Container.$c as C+import qualified InputData.$i+#include "../Driver.inc.hs"+$addons+#include "../Benchmark/${c#Int}-like.inc.hs"+$benchmark+EOF+  done+done