railsbench 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
data/script/perf_bench ADDED
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
4
+
5
+ unless ENV['RAILS_ROOT']
6
+ $stderr.puts("\nOOPS: can't benchmark unless RAILS_ROOT is set")
7
+ $stderr.puts("\nbenchmarking aborted!")
8
+ exit 1
9
+ end
10
+
11
+ trap("INT") { $stderr.puts("benchmarking aborted!"); exit!(-1) }
12
+
13
+ module Benchmark
14
+ if ENV['RAILS_BENCHMARK_FILE']
15
+ OUTPUT = File.open(ENV['RAILS_BENCHMARK_FILE'], "a+")
16
+ SYNC = false
17
+ else
18
+ OUTPUT = STDERR
19
+ end
20
+ end
21
+ require "benchmark"
22
+ include Benchmark
23
+
24
+ bm(32) do |test|
25
+ test.report("loading environment") do
26
+ require 'railsbench/railsbenchmark'
27
+ require ENV['RAILS_ROOT'] + '/config/benchmarks'
28
+ end
29
+
30
+ trap("INT") do
31
+ $stderr.puts "clearing database connections ..."
32
+ ActiveRecord::Base.send :clear_all_cached_connections!
33
+ $stderr.puts "benchmarking aborted!"
34
+ exit!(-1)
35
+ end
36
+
37
+ benchmarks = YAML::load(File.open(ENV['RAILS_ROOT'] + "/config/benchmarks.yml"))
38
+ benchmark_name = "default"
39
+ ARGV.each{ |arg| benchmark_name = $1 if arg =~ /-bm=([a-zA-Z_0-9]+)/ }
40
+
41
+ RAILS_BENCHMARKER.iterations = ARGV[0].to_i
42
+ RAILS_BENCHMARKER.url_spec = benchmarks
43
+ RAILS_BENCHMARKER.setup_test_urls(benchmark_name)
44
+ RAILS_BENCHMARKER.establish_test_session
45
+ RAILS_BENCHMARKER.warmup
46
+
47
+ if ARGV.include?('-mix')
48
+ RAILS_BENCHMARKER.run_url_mix(test)
49
+ else
50
+ RAILS_BENCHMARKER.run_urls(test)
51
+ end
52
+ end
53
+
54
+ Benchmark::OUTPUT.close unless Benchmark::OUTPUT.nil? || !ENV['RAILS_BENCHMARK_FILE']
55
+
56
+ __END__
57
+
58
+ ### Local Variables: ***
59
+ ### mode:ruby ***
60
+ ### End: ***
61
+
62
+ # Copyright (C) 2005, 2006 Stefan Kaes
63
+ #
64
+ # This program is free software; you can redistribute it and/or modify
65
+ # it under the terms of the GNU General Public License as published by
66
+ # the Free Software Foundation; either version 2 of the License, or
67
+ # (at your option) any later version.
68
+ #
69
+ # This program is distributed in the hope that it will be useful,
70
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
71
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72
+ # GNU General Public License for more details.
73
+ #
74
+ # You should have received a copy of the GNU General Public License
75
+ # along with this program; if not, write to the Free Software
76
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
data/script/perf_comp ADDED
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
4
+ require 'railsbench/perf_info'
5
+
6
+ narrow = ARGV.delete('-narrow') || ARGV.delete('-n')
7
+ skip_urls = ARGV.delete('-skip_urls') || ARGV.delete('-s')
8
+
9
+ if ARGV.length < 2
10
+ $stderr.puts "perfcomp: not enough arguments!"
11
+ $stderr.puts "usage: perf_comp [-n[arrow]] [-s[kip_urls]] file1 file2"
12
+ exit 1
13
+ elsif ARGV.length > 2
14
+ $stderr.puts "perfcomp: too many arguments!"
15
+ $stderr.puts "usage: perf_comp [-n[arrow]] [-s[kip_urls]] file1 file2"
16
+ exit 1
17
+ end
18
+
19
+ files = []
20
+ configs = []
21
+ pi = []
22
+
23
+ ARGV.each do |arg|
24
+ files << File.open_or_die(arg)
25
+ pi << PerfInfo.new(files.last)
26
+ end
27
+
28
+ if pi[0].keys != pi[1].keys
29
+ $stderr.puts "perfcomp: can't compare runs with differing requests!"
30
+ exit 1
31
+ else
32
+ keys = pi[0].keys
33
+ end
34
+
35
+ iter1 = pi[0].iterations
36
+ iter2 = pi[1].iterations
37
+
38
+ if iter1 != iter2
39
+ $stderr.puts "perfcomp: scaling performance data: iterations of run 1 and run 2 differ: #{iter1}/#{iter2}"
40
+ end
41
+
42
+ if iter1 < iter2
43
+ c1 = iter2 / iter1
44
+ c2 = 1
45
+ else
46
+ c1 = 1
47
+ c2 = iter1 / iter2
48
+ end
49
+
50
+ printf "perf data file 1: #{files[0].path}\n"
51
+ printf " requests=#{iter1}, options=#{pi[0].options}\n\n"
52
+ printf "perf data file 2: #{files[1].path}\n"
53
+ printf " requests=#{iter2}, options=#{pi[1].options}\n\n"
54
+
55
+ if narrow
56
+ printf "%-3s %9s %9s %7s %7s %8s %8s %6s\n",
57
+ 'page', 'c1 real', 'c2 real', 'c1 r/s', 'c2 r/s', 'c1 ms/r', 'c2 ms/r', 'c1/c2'
58
+ else
59
+ printf "%-32s %9s %9s %7s %7s %8s %8s %6s\n",
60
+ 'page', 'c1 real', 'c2 real', 'c1 r/s', 'c2 r/s', 'c1 ms/r', 'c2 ms/r', 'c1/c2'
61
+ end
62
+
63
+ keys.each_with_index do |k, index|
64
+ # average runtime
65
+ t1 = pi[0].timings_mean(k) * c1
66
+ t2 = pi[1].timings_mean(k) * c2
67
+ urls1 = pi[0].requests_per_key
68
+ urls2 = pi[1].requests_per_key
69
+
70
+ # requests per second
71
+ rps1 = iter1*urls1*c1/t1
72
+ rps2 = iter2*urls2*c2/t2
73
+
74
+ # milliseconds per request
75
+ mspr1 = t1*1000/(iter1*urls1*c1)
76
+ mspr2 = t2*1000/(iter2*urls2*c2)
77
+
78
+ if narrow
79
+ printf "%2d: %9.5f %9.5f %7.1f %7.1f %8.2f %8.2f %6.2f\n",
80
+ (index+1), t1, t2, rps1, rps2, mspr1, mspr2, t1/t2
81
+ else
82
+ printf "%-32s %9.5f %9.5f %7.1f %7.1f %8.2f %8.2f %6.2f\n",
83
+ truncate(k), t1, t2, rps1, rps2, mspr1, mspr2, t1/t2
84
+ end
85
+ end
86
+
87
+ total_requests_run1 = pi[0].request_count
88
+ total_requests_run2 = pi[1].request_count
89
+ total_time1 = pi[0].total_time_mean * c1
90
+ total_time2 = pi[1].total_time_mean * c2
91
+ total_rps1 = total_requests_run1 * c1 / total_time1
92
+ total_rps2 = total_requests_run2 * c2 / total_time2
93
+ total_mspr1 = total_time1 * 1000 / (total_requests_run1 * c1)
94
+ total_mspr2 = total_time2 * 1000 / (total_requests_run2 * c2)
95
+
96
+ if narrow
97
+ printf "\n%4s %9.5f %9.5f %7.1f %7.1f %8.2f %8.2f %6.2f\n",
98
+ "all:", total_time1, total_time2,
99
+ total_rps1, total_rps2, total_mspr1, total_mspr2,
100
+ total_time1/total_time2
101
+ else
102
+ printf "\n%-32s %9.5f %9.5f %7.1f %7.1f %8.2f %8.2f %6.2f\n",
103
+ "all requests", total_time1, total_time2,
104
+ total_rps1, total_rps2, total_mspr1, total_mspr2,
105
+ total_time1/total_time2
106
+ end
107
+
108
+ if pi[0].gc_stats? && pi[1].gc_stats?
109
+ c1 = pi[0].gc_calls_mean
110
+ t1 = pi[0].gc_time_mean
111
+ c2 = pi[1].gc_calls_mean
112
+ t2 = pi[1].gc_time_mean
113
+ factor = (c1-c2==0) ? 1 : c1/c2
114
+
115
+ if narrow
116
+ printf "\n%-4s %9s %9s %7s %7s %8s %8s %6s\n",
117
+ "GC:", "c1 real", "c2 real", "c1 #gc", "c2 #gc", "c1 gc%", "c2 gc%", "c1/c2"
118
+ printf "%-4s %9.5f %9.5f %7.1f %7.1f %8.2f %8.2f %6.2f\n",
119
+ "", t1, t2, c1, c2, (t1/total_time1)*100, (t2/total_time2)*100, factor
120
+ else
121
+ printf "\n%-32s %9s %9s %7s %7s %8s %8s %6s\n",
122
+ "garbage collection stats", "c1 real", "c2 real", "c1 #gc", "c2 #gc", "c1 gc%", "c2 gc%", "c1/c2"
123
+ printf "%-32s %9.5f %9.5f %7.1f %7.1f %8.2f %8.2f %6.2f\n",
124
+ "", t1, t2, c1, c2, (t1/total_time1)*100, (t2/total_time2)*100, factor
125
+ end
126
+ end
127
+
128
+ if narrow and !skip_urls
129
+ puts "\nurls:"
130
+ keys.each_with_index do |k, index|
131
+ printf "%2d: %s\n", (index+1) , k
132
+ end
133
+ end
134
+
135
+ __END__
136
+
137
+ ### Local Variables: ***
138
+ ### mode:ruby ***
139
+ ### End: ***
140
+
141
+ # Copyright (C) 2005, 2006 Stefan Kaes
142
+ #
143
+ # This program is free software; you can redistribute it and/or modify
144
+ # it under the terms of the GNU General Public License as published by
145
+ # the Free Software Foundation; either version 2 of the License, or
146
+ # (at your option) any later version.
147
+ #
148
+ # This program is distributed in the hope that it will be useful,
149
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
150
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151
+ # GNU General Public License for more details.
152
+ #
153
+ # You should have received a copy of the GNU General Public License
154
+ # along with this program; if not, write to the Free Software
155
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ options = ""
4
+ if ARGV.length!=2
5
+ puts "usage: perf_diff_gc file1 file2"
6
+ exit 1
7
+ end
8
+ files=[]
9
+ ARGV.each do |arg|
10
+ fn = arg
11
+ fn = fn.sub(/^\/([cdefgh])(\/)/, '\1:\2') if RUBY_PLATFORM =~ /win32/
12
+ begin
13
+ if File.stat(fn).readable?
14
+ files << File.open(fn)
15
+ else
16
+ print "file #{fn} is unreadable\n"
17
+ exit 1
18
+ end
19
+ rescue
20
+ print "file #{fn} does not exist\n"
21
+ exit 1
22
+ end
23
+ end
24
+
25
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
26
+ require 'railsbench/gc_info'
27
+
28
+ printf "GC data file1: #{File.expand_path(files[0].path)}\n"
29
+ printf "GC data file2: #{File.expand_path(files[1].path)}\n\n"
30
+
31
+ gcis = files.map{|file| GCInfo.new(file)}
32
+ files.each{|file| file.close}
33
+
34
+ printf "number of requests: %d/%d\n", gcis[0].num_requests, gcis[1].num_requests
35
+
36
+ printf " %12s %12s %7s\n", "c1", "c2", "c1/c2"
37
+ printf "collections : %12.2f %12.2f %7.2f\n",
38
+ (n1 = gcis[0].collections),
39
+ (n2 = gcis[1].collections),
40
+ n1.to_f/n2
41
+ printf "garbage total : %12.2f %12.2f %7.2f\n",
42
+ (n1 = gcis[0].garbage_produced),
43
+ (n2 = gcis[1].garbage_produced),
44
+ n1.to_f/n2
45
+ printf "gc time total (sec) : %12.2f %12.2f %7.2f\n",
46
+ (n1 = gcis[0].time_total.to_f/1000),
47
+ (n2 = gcis[1].time_total.to_f/1000),
48
+ n1/n2
49
+ printf "garbage per request : %12.2f %12.2f %7.2f\n",
50
+ (n1 = gcis[0].garbage_produced.to_f/gcis[0].num_requests),
51
+ (n2 = gcis[1].garbage_produced.to_f/gcis[1].num_requests),
52
+ n1/n2
53
+ printf "requests per collection: %12.2f %12.2f %7.2f\n",
54
+ (n1 = gcis[0].num_requests.to_f/gcis[0].collections),
55
+ (n2 = gcis[1].num_requests.to_f/gcis[1].collections),
56
+ n1/n2
57
+
58
+ printf "\n %12s %12s %9s %9s %9s %9s\n",
59
+ "c1 mean", "c2 mean", "c1 min", "c2 min", "c1 max", "c2 max"
60
+
61
+ number_format = "%12.2f %12.2f %9d %9d %9d %9d"
62
+
63
+ printf "gc time(ms): #{number_format}\n",
64
+ gcis[0].time_mean, gcis[1].time_mean,
65
+ gcis[0].time_min, gcis[1].time_min,
66
+ gcis[0].time_max, gcis[1].time_max
67
+
68
+ printf "heap slots : #{number_format}\n",
69
+ gcis[0].processed_mean, gcis[1].processed_mean,
70
+ gcis[0].processed_min, gcis[1].processed_min,
71
+ gcis[0].processed_max, gcis[1].processed_max
72
+
73
+ printf "live : #{number_format}\n",
74
+ gcis[0].live_mean, gcis[1].live_mean,
75
+ gcis[0].live_min, gcis[1].live_min,
76
+ gcis[0].live_max, gcis[1].live_max
77
+
78
+ printf "freed : #{number_format}\n",
79
+ gcis[0].freed_mean, gcis[1].freed_mean,
80
+ gcis[0].freed_min, gcis[1].freed_min,
81
+ gcis[0].freed_max, gcis[1].freed_max
82
+
83
+ printf "freelist : #{number_format}\n",
84
+ gcis[0].freelist_mean, gcis[1].freelist_mean,
85
+ gcis[0].freelist_min, gcis[1].freelist_min,
86
+ gcis[0].freelist_max, gcis[1].freelist_max
87
+
88
+
89
+ __END__
90
+
91
+ ### Local Variables: ***
92
+ ### mode:ruby ***
93
+ ### End: ***
94
+
95
+ # Copyright (C) 2005, 2006 Stefan Kaes
96
+ #
97
+ # This program is free software; you can redistribute it and/or modify
98
+ # it under the terms of the GNU General Public License as published by
99
+ # the Free Software Foundation; either version 2 of the License, or
100
+ # (at your option) any later version.
101
+ #
102
+ # This program is distributed in the hope that it will be useful,
103
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
104
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105
+ # GNU General Public License for more details.
106
+ #
107
+ # You should have received a copy of the GNU General Public License
108
+ # along with this program; if not, write to the Free Software
109
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
data/script/perf_diff ADDED
@@ -0,0 +1,48 @@
1
+ #!/bin/sh
2
+ # set -x
3
+
4
+ if [ $# -lt 4 ]; then
5
+ echo "usage: perf_diff iterations common-options options1 options4 [conf-name1] [conf-name2]"
6
+ echo "example: perf_diff 100 \"-bm=all\" \"-log\" \"-nocache\" c1 c2"
7
+ exit 1
8
+ fi
9
+
10
+ BINDIR=`dirname $0`
11
+ test -z "$RAILS_PERF_DATA" && RAILS_PERF_DATA=$HOME
12
+
13
+ ITER="$1"
14
+ COMMON="$2"
15
+ OPT1="$3"
16
+ OPT2="$4"
17
+ DATE=`date +%m-%d`
18
+ BENCHMARK=""
19
+ for opt in $COMMON; do
20
+ case $opt in
21
+ -bm=*) BENCHMARK=${opt#-bm=};;
22
+ esac
23
+ done
24
+
25
+ if [ $# -gt 4 ]; then
26
+ FILE1="$RAILS_PERF_DATA/${DATE}.${BENCHMARK}.$5.txt"
27
+ else
28
+ FILE1="$RAILS_PERF_DATA/perf_run1.${BENCHMARK}.txt"
29
+ fi
30
+ if [ $# -gt 5 ]; then
31
+ FILE2="$RAILS_PERF_DATA/${DATE}.${BENCHMARK}.$6.txt"
32
+ else
33
+ FILE2="$RAILS_PERF_DATA/perf_run2.${BENCHMARK}.txt"
34
+ fi
35
+
36
+ unset RUBY_GC_STATS
37
+
38
+ PERF_OPTIONS="$ITER $COMMON $OPT1"
39
+ RAILS_BENCHMARK_FILE=$FILE1 $BINDIR/perf_loop $PERF_OPTIONS || exit 1
40
+ ruby $BINDIR/perf_times $FILE1
41
+ echo;echo
42
+
43
+ PERF_OPTIONS="$ITER $COMMON $OPT2"
44
+ RAILS_BENCHMARK_FILE=$FILE2 $BINDIR/perf_loop $PERF_OPTIONS || exit 1
45
+ ruby $BINDIR/perf_times $FILE2
46
+ echo;echo
47
+
48
+ ruby $BINDIR/perf_comp -narrow -skip_urls $FILE1 $FILE2
@@ -0,0 +1,89 @@
1
+ #!/bin/sh
2
+ # set -x
3
+
4
+ if [ $# -lt 4 ]; then
5
+ echo "usage: perf_diff_gc iterations options1 options2 [conf-name1] [conf-name2]"
6
+ echo "example: perf_diff_gc 100 \"-bm=default\" \"-log\" \"-nocache\" c1 c2"
7
+ exit 1
8
+ fi
9
+
10
+ BINDIR=`dirname $0`
11
+ test -z "$RAILS_PERF_DATA" && RAILS_PERF_DATA=$HOME
12
+
13
+ ITER="$1"
14
+ COMMON="$2"
15
+ OPT1="$3"
16
+ OPT2="$4"
17
+ BENCHMARK=""
18
+ WARMUP="-warmup"
19
+
20
+ DATE=`date +%m-%d`
21
+
22
+
23
+ if [ $# -gt 4 ]; then
24
+ FILE1="$RAILS_PERF_DATA/${DATE}${BENCHMARK}.$5.gc.txt"
25
+ else
26
+ FILE1="$RAILS_PERF_DATA/perf_run1${BENCHMARK}.gc.txt"
27
+ fi
28
+ if [ $# -gt 5 ]; then
29
+ FILE2="$RAILS_PERF_DATA/${DATE}${BENCHMARK}.$6.gc.txt"
30
+ else
31
+ FILE2="$RAILS_PERF_DATA/perf_run2${BENCHMARK}.gc.txt"
32
+ fi
33
+
34
+ OLD_RUBY_HEAP_MIN_SLOTS=$RUBY_HEAP_MIN_SLOTS
35
+ OLD_RUBY_GC_MALLOC_LIMIT=$RUBY_GC_MALLOC_LIMIT
36
+ OLD_RUBY_HEAP_FREE_MIN=$RUBY_HEAP_FREE_MIN
37
+
38
+ PERF_OPTIONS="$ITER $WARMUP $COMMON $OPT1"
39
+
40
+ patched_gc="no"
41
+ for opt in $COMMON $OPT1; do
42
+ case $opt in
43
+ -gc=*) patched_gc=${opt#-gc=};;
44
+ esac
45
+ done
46
+
47
+ if [ "${patched_gc}" = "no" ]; then
48
+ unset RUBY_HEAP_MIN_SLOTS RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN
49
+ else
50
+ . $RAILS_ROOT/config/${patched_gc}.gc
51
+ export RUBY_HEAP_MIN_SLOTS RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN
52
+ fi
53
+
54
+ echo "benchmarking GC performance with options $PERF_OPTIONS"
55
+ echo
56
+
57
+ (RUBY_GC_STATS=1 RUBY_GC_DATA_FILE=$FILE1 ruby $BINDIR/run_urls $PERF_OPTIONS >/dev/null) \
58
+ && ruby $BINDIR/perf_times_gc $FILE1
59
+ echo;echo
60
+
61
+ PERF_OPTIONS="$ITER $WARMUP $COMMON $OPT2"
62
+
63
+ patched_gc="no"
64
+ for opt in $COMMON $OPT2; do
65
+ case $opt in
66
+ -gc=*) patched_gc=${opt#-gc=};;
67
+ esac
68
+ done
69
+
70
+ if [ "${patched_gc}" = "no" ]; then
71
+ unset RUBY_HEAP_MIN_SLOTS RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN
72
+ else
73
+ . $RAILS_ROOT/config/${patched_gc}.gc
74
+ export RUBY_HEAP_MIN_SLOTS RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN
75
+ fi
76
+
77
+ echo "benchmarking GC performance with options $PERF_OPTIONS"
78
+ echo
79
+
80
+ (RUBY_GC_STATS=1 RUBY_GC_DATA_FILE=$FILE2 ruby $BINDIR/run_urls $PERF_OPTIONS >/dev/null) \
81
+ && ruby $BINDIR/perf_times_gc $FILE2
82
+ echo;echo
83
+
84
+ unset RUBY_HEAP_MIN_SLOTS RUBY_GC_MALLOC_LIMIT RUBY_HEAP_FREE_MIN
85
+
86
+ echo "benchmark comparison data"
87
+ echo
88
+
89
+ ruby $BINDIR/perf_comp_gc $FILE1 $FILE2