railsbench 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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