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 +30/−0
- README +59/−0
- Setup.hs +3/−0
- containers-benchmark.cabal +68/−0
- scripts/benchmark.sh +13/−0
- scripts/cmp.pl +69/−0
- scripts/cmp.sh +3/−0
- scripts/collect.pl +75/−0
- scripts/compile.sh +13/−0
- scripts/custom_containers.sh +23/−0
- scripts/ghc.sh +38/−0
- scripts/run.sh +42/−0
- scripts/see.sh +15/−0
- scripts/system_containers.sh +10/−0
- src/Benchmark/Map-like.inc.hs +58/−0
- src/Benchmark/Set-like.inc.hs +48/−0
- src/Container/IntMap.hs +3/−0
- src/Container/IntSet.hs +3/−0
- src/Container/Map.hs +3/−0
- src/Container/Set.hs +3/−0
- src/Driver.inc.hs +40/−0
- src/InputData/ByteString.hs +11/−0
- src/InputData/Int.hs +10/−0
- src/InputData/IntegerBig.hs +10/−0
- src/InputData/IntegerSmall.hs +10/−0
- src/InputData/String.hs +16/−0
- src/Main.hs +33/−0
- src/Variants/IntMap_Int.hs +12/−0
- src/Variants/IntSet_Int.hs +12/−0
- src/Variants/Map_ByteString.hs +14/−0
- src/Variants/Map_Int.hs +12/−0
- src/Variants/Map_IntegerBig.hs +12/−0
- src/Variants/Map_IntegerSmall.hs +12/−0
- src/Variants/Map_String.hs +14/−0
- src/Variants/Set_ByteString.hs +14/−0
- src/Variants/Set_Int.hs +12/−0
- src/Variants/Set_IntegerBig.hs +12/−0
- src/Variants/Set_IntegerSmall.hs +12/−0
- src/Variants/Set_String.hs +14/−0
- src/Variants/gen.sh +38/−0
+ 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