kamal-railsbench 0.9.9.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/BUGS +2 -0
- data/CHANGELOG +2124 -0
- data/GCPATCH +73 -0
- data/INSTALL +75 -0
- data/LICENSE +222 -0
- data/Manifest.txt +53 -0
- data/PROBLEMS +56 -0
- data/README +337 -0
- data/Rakefile +51 -0
- data/bin/railsbench +80 -0
- data/config/benchmarking.rb +21 -0
- data/config/benchmarks.rb +21 -0
- data/config/benchmarks.yml +2 -0
- data/images/empty.png +0 -0
- data/images/minus.png +0 -0
- data/images/plus.png +0 -0
- data/install.rb +70 -0
- data/latest_changes.txt +18 -0
- data/lib/benchmark.rb +576 -0
- data/lib/railsbench/benchmark.rb +576 -0
- data/lib/railsbench/benchmark_specs.rb +63 -0
- data/lib/railsbench/gc_info.rb +158 -0
- data/lib/railsbench/perf_info.rb +146 -0
- data/lib/railsbench/perf_utils.rb +202 -0
- data/lib/railsbench/railsbenchmark.rb +640 -0
- data/lib/railsbench/version.rb +9 -0
- data/lib/railsbench/write_headers_only.rb +15 -0
- data/postinstall.rb +12 -0
- data/ruby184gc.patch +516 -0
- data/ruby185gc.patch +562 -0
- data/ruby186gc.patch +564 -0
- data/ruby19gc.patch +2425 -0
- data/script/convert_raw_data_files +49 -0
- data/script/generate_benchmarks +171 -0
- data/script/perf_bench +74 -0
- data/script/perf_comp +151 -0
- data/script/perf_comp_gc +113 -0
- data/script/perf_diff +48 -0
- data/script/perf_diff_gc +53 -0
- data/script/perf_html +103 -0
- data/script/perf_plot +225 -0
- data/script/perf_plot_gc +254 -0
- data/script/perf_prof +87 -0
- data/script/perf_run +39 -0
- data/script/perf_run_gc +40 -0
- data/script/perf_table +104 -0
- data/script/perf_tex +58 -0
- data/script/perf_times +66 -0
- data/script/perf_times_gc +94 -0
- data/script/run_urls +57 -0
- data/setup.rb +1585 -0
- data/test/railsbench_test.rb +11 -0
- data/test/test_helper.rb +2 -0
- metadata +133 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
require 'railsbench/benchmark_specs'
|
7
|
+
|
8
|
+
ARGV.each do |file_name|
|
9
|
+
backup_file_name = file_name + '~'
|
10
|
+
FileUtils.mv(file_name, backup_file_name)
|
11
|
+
File.open(backup_file_name) do |infile|
|
12
|
+
bench_name = Hash.new{ |hash,key| hash[key] = key }
|
13
|
+
File.open(file_name, "w") do |outfile|
|
14
|
+
infile.each_line do |line|
|
15
|
+
case line
|
16
|
+
when /-bm=([^\s]+)/
|
17
|
+
# $stderr.puts "-bm=#{$1}"
|
18
|
+
outfile.puts(line)
|
19
|
+
benchmarks = BenchmarkSpec.load($1)
|
20
|
+
benchmarks.each{|spec| bench_name[spec.uri] = spec.name}
|
21
|
+
when /^(.*)(\s+[\d\.]+\s+[\d\.]+\s+[\d\.]+\s+\(\s*[\d\.]+\s*\))$/
|
22
|
+
l = $1.length
|
23
|
+
# $stderr.printf "%-#{l}s%s\n", $1.strip, $2
|
24
|
+
outfile.printf "%-#{l}s%s\n", bench_name[$1.strip], $2
|
25
|
+
else
|
26
|
+
outfile.puts(line)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
__END__
|
34
|
+
|
35
|
+
# Copyright (C) 2007, 2008 Stefan Kaes
|
36
|
+
#
|
37
|
+
# This program is free software; you can redistribute it and/or modify
|
38
|
+
# it under the terms of the GNU General Public License as published by
|
39
|
+
# the Free Software Foundation; either version 2 of the License, or
|
40
|
+
# (at your option) any later version.
|
41
|
+
#
|
42
|
+
# This program is distributed in the hope that it will be useful,
|
43
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
44
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
45
|
+
# GNU General Public License for more details.
|
46
|
+
#
|
47
|
+
# You should have received a copy of the GNU General Public License
|
48
|
+
# along with this program; if not, write to the Free Software
|
49
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
@@ -0,0 +1,171 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
unless ENV['RAILS_ROOT']
|
4
|
+
if File.directory?("config") && File.exists?("config/environment.rb")
|
5
|
+
ENV['RAILS_ROOT'] = File.expand_path(".")
|
6
|
+
else
|
7
|
+
$stderr.puts("\nperf_bench: can't generate benchmarks unless RAILS_ROOT is set")
|
8
|
+
$stderr.puts("\nbenchmarking aborted!")
|
9
|
+
exit 1
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
require "#{ENV['RAILS_ROOT']}/config/environment"
|
14
|
+
require 'application'
|
15
|
+
|
16
|
+
if ARGV.first == "help"
|
17
|
+
puts <<-"endhelp"
|
18
|
+
usage: railsbench generate_benchmarks -excluded_actions=<regexp> -excluded_controllers=<controller_list>
|
19
|
+
1) loads your application\'s routes and generates a benchmarks.yml file
|
20
|
+
containing benchmark definitions for each route found
|
21
|
+
2) for named routes, benchmark names are derived from the route name
|
22
|
+
3) for routes defined via map.connect, the benchmark name is derived
|
23
|
+
from the controller and action
|
24
|
+
4) for each controller, a benchmark consisting of all controller actions
|
25
|
+
is generated (named after the controller file name)
|
26
|
+
5) generates a benchmark named 'all_controllers', consisting of all
|
27
|
+
benchmarks generated in step 4
|
28
|
+
endhelp
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
excluded_controllers = ["application"]
|
33
|
+
excluded_actions = /delete|destroy/
|
34
|
+
ARGV.each do |arg|
|
35
|
+
excluded_controllers += $1.split(/, */).compact if arg =~ /-excluded_controllers=(.*)/
|
36
|
+
excluded_actions = Regexp.new($1.gsub(/,/, '|')) if arg =~ /-excluded_actions=(.*)/
|
37
|
+
end
|
38
|
+
|
39
|
+
benchmark_config = File.expand_path "#{RAILS_ROOT}/config/benchmarks.yml"
|
40
|
+
|
41
|
+
if File.exist? benchmark_config
|
42
|
+
benchmarks = YAML::load(File.open(benchmark_config)) || {}
|
43
|
+
else
|
44
|
+
benchmarks = {}
|
45
|
+
end
|
46
|
+
|
47
|
+
VALID_KEYS = %w(uri action controller new_session query_params)
|
48
|
+
|
49
|
+
def dump_entry(name, entry, io = $stdout)
|
50
|
+
io.puts "#{name}:"
|
51
|
+
if entry.is_a? Hash
|
52
|
+
VALID_KEYS.each do |key|
|
53
|
+
io.printf " %-15s %s\n", key + ':', entry[key] if entry.has_key? key
|
54
|
+
end
|
55
|
+
io.puts
|
56
|
+
elsif entry.is_a? String
|
57
|
+
io.printf " %s\n\n", entry
|
58
|
+
else
|
59
|
+
raise "unsupported YAML entry"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
unless Rails::VERSION::STRING >= "1.2"
|
64
|
+
$stderr.puts "Rails version #{Rails::VERSION::STRING} is not supported. please use a 1.2.x or later variety."
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
|
68
|
+
rs = ActionController::Routing::Routes
|
69
|
+
|
70
|
+
named_routes_map = rs.named_routes.to_a.inject({}){|h,(name,route)| h[route] = name; h}
|
71
|
+
controller_action_map = {}
|
72
|
+
has_default_route = false
|
73
|
+
|
74
|
+
out = File.open(benchmark_config, "w")
|
75
|
+
|
76
|
+
rs.routes.to_a.each do |route|
|
77
|
+
uri = route.segments.map(&:to_s).join
|
78
|
+
(has_default_route = true; next) if uri == "/:controller/:action/:id/"
|
79
|
+
controller = route.requirements[:controller].to_s
|
80
|
+
action = route.requirements[:action].to_s
|
81
|
+
controller_action = "#{controller}_#{action}"
|
82
|
+
file_name = "#{controller}_controller"
|
83
|
+
benchmark_name = (named_routes_map[route] || controller_action).to_s
|
84
|
+
entry = (benchmarks[benchmark_name] || {}).reverse_merge "uri" => uri, "controller" => controller, "action" => action
|
85
|
+
benchmarks.delete benchmark_name
|
86
|
+
if action =~ excluded_actions
|
87
|
+
$stderr.puts "ignored action: #{action}"
|
88
|
+
benchmarks[file_name] = ((benchmarks[file_name]||"").split(/, */) - [benchmark_name]).uniq.join(', ')
|
89
|
+
next
|
90
|
+
end
|
91
|
+
if excluded_controllers.include? controller
|
92
|
+
$stderr.puts "ignored controller: #{controller}"
|
93
|
+
benchmarks["all_controllers"] = ((benchmarks["all_controllers"]||"").split(/, */) - [file_name]).uniq.join(', ')
|
94
|
+
next
|
95
|
+
end
|
96
|
+
dump_entry benchmark_name, entry, out
|
97
|
+
controller_action_map[controller_action] = true
|
98
|
+
benchmarks[file_name] = ((benchmarks[file_name]||"").split(/, */) + [benchmark_name]).uniq.join(', ')
|
99
|
+
benchmarks["all_controllers"] = ((benchmarks["all_controllers"]||"").split(/, */) + [file_name]).uniq.join(', ')
|
100
|
+
end
|
101
|
+
|
102
|
+
if has_default_route
|
103
|
+
$stderr.puts "warning: you are still using the default route"
|
104
|
+
Dir["#{RAILS_ROOT}/app/controllers/*.rb"].each do |file|
|
105
|
+
file_name = File.basename(file).sub(/\.rb$/,'')
|
106
|
+
controller_name = file_name.sub(/_controller$/,'')
|
107
|
+
if excluded_controllers.include? controller_name
|
108
|
+
$stderr.puts "ignored controller: #{controller_name}"
|
109
|
+
benchmarks["all_controllers"] = ((benchmarks["all_controllers"]||"").split(/, */) - [file_name]).uniq.join(', ')
|
110
|
+
next
|
111
|
+
end
|
112
|
+
begin
|
113
|
+
controller = file_name.classify.constantize
|
114
|
+
controller.action_methods.map(&:to_s).each do |method|
|
115
|
+
benchmark_name = "#{controller_name}_#{method}"
|
116
|
+
next if controller_action_map[benchmark_name]
|
117
|
+
uri = rs.generate({:controller => controller_name ,:action => method},{})
|
118
|
+
entry = (benchmarks[benchmark_name] || {}).reverse_merge "uri" => uri, "controller" => controller_name, "action" => method
|
119
|
+
benchmarks.delete benchmark_name
|
120
|
+
if method =~ excluded_actions
|
121
|
+
$stderr.puts "ignored action: #{method}"
|
122
|
+
benchmarks[file_name] = ((benchmarks[file_name]||"").split(/, */) - [benchmark_name]).uniq.join(', ')
|
123
|
+
next
|
124
|
+
end
|
125
|
+
dump_entry benchmark_name, entry, out
|
126
|
+
benchmarks[file_name] = ((benchmarks[file_name]||"").split(/, */) + [benchmark_name]).uniq.join(', ')
|
127
|
+
benchmarks["all_controllers"] = ((benchmarks["all_controllers"]||"").split(/, */) + [file_name]).uniq.join(', ')
|
128
|
+
end
|
129
|
+
rescue MissingSourceFile, NoMethodError, ActionController::RoutingError
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# dump remaining benchmarks
|
135
|
+
all_entry = benchmarks.delete "all_controllers"
|
136
|
+
|
137
|
+
benchmarks.delete_if do |k,v|
|
138
|
+
v.is_a?(Hash) && (v["action"].to_s =~ excluded_actions || v["controller"].to_s =~ excluded_controllers)
|
139
|
+
end
|
140
|
+
|
141
|
+
generated_controller_benchmarks, others = benchmarks.partition{|k,v| k =~ /_controller$/}
|
142
|
+
|
143
|
+
generated_controller_benchmarks.sort_by(&:first).each do |benchmark_name, entry|
|
144
|
+
dump_entry benchmark_name, entry, out
|
145
|
+
end
|
146
|
+
|
147
|
+
dump_entry "all_controllers", all_entry, out
|
148
|
+
|
149
|
+
others.each do |benchmark_name, entry|
|
150
|
+
dump_entry benchmark_name, entry, out
|
151
|
+
end
|
152
|
+
|
153
|
+
out.close unless out.nil?
|
154
|
+
|
155
|
+
__END__
|
156
|
+
|
157
|
+
# Copyright (C) 2007, 2008 Stefan Kaes
|
158
|
+
#
|
159
|
+
# This program is free software; you can redistribute it and/or modify
|
160
|
+
# it under the terms of the GNU General Public License as published by
|
161
|
+
# the Free Software Foundation; either version 2 of the License, or
|
162
|
+
# (at your option) any later version.
|
163
|
+
#
|
164
|
+
# This program is distributed in the hope that it will be useful,
|
165
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
166
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
167
|
+
# GNU General Public License for more details.
|
168
|
+
#
|
169
|
+
# You should have received a copy of the GNU General Public License
|
170
|
+
# along with this program; if not, write to the Free Software
|
171
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
data/script/perf_bench
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
|
4
|
+
|
5
|
+
unless ENV['RAILS_ROOT']
|
6
|
+
if File.directory?("config") && File.exists?("config/environment.rb")
|
7
|
+
ENV['RAILS_ROOT'] = File.expand_path(".")
|
8
|
+
else
|
9
|
+
$stderr.puts("\nperf_bench: can't benchmark unless RAILS_ROOT is set")
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
trap("INT") { $stderr.puts("benchmarking aborted!"); exit!(-1) }
|
15
|
+
|
16
|
+
module Benchmark
|
17
|
+
if ENV['RAILS_BENCHMARK_FILE']
|
18
|
+
OUTPUT = File.open(ENV['RAILS_BENCHMARK_FILE'], "a+")
|
19
|
+
SYNC = false
|
20
|
+
else
|
21
|
+
OUTPUT = STDERR
|
22
|
+
end
|
23
|
+
end
|
24
|
+
require "benchmark"
|
25
|
+
|
26
|
+
Benchmark.bm(32) do |test|
|
27
|
+
test.report("loading environment") do
|
28
|
+
require 'railsbench/railsbenchmark'
|
29
|
+
require ENV['RAILS_ROOT'] + '/config/benchmarks'
|
30
|
+
end
|
31
|
+
|
32
|
+
trap("INT") do
|
33
|
+
$stderr.print "clearing database connections ..."
|
34
|
+
ActiveRecord::Base.send :clear_all_cached_connections! if ActiveRecord::Base.respond_to?(:clear_all_cached_connections)
|
35
|
+
ActiveRecord::Base.send :clear_all_connections! if ActiveRecord::Base.respond_to?(:clear_all_connections)
|
36
|
+
$stderr.puts
|
37
|
+
$stderr.puts "benchmarking aborted!"
|
38
|
+
exit!(-1)
|
39
|
+
end
|
40
|
+
|
41
|
+
benchmark_name = "default"
|
42
|
+
ARGV.each{ |arg| benchmark_name = $1 if arg =~ /-bm=([a-zA-Z_0-9]+)/ }
|
43
|
+
|
44
|
+
RAILS_BENCHMARKER.iterations = ARGV[0].to_i
|
45
|
+
RAILS_BENCHMARKER.setup_test_urls(benchmark_name)
|
46
|
+
RAILS_BENCHMARKER.establish_test_session
|
47
|
+
RAILS_BENCHMARKER.warmup
|
48
|
+
|
49
|
+
if ARGV.include?('-mix')
|
50
|
+
RAILS_BENCHMARKER.run_url_mix(test)
|
51
|
+
else
|
52
|
+
RAILS_BENCHMARKER.run_urls(test)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Benchmark::OUTPUT.close unless Benchmark::OUTPUT.nil? || !ENV['RAILS_BENCHMARK_FILE']
|
57
|
+
|
58
|
+
__END__
|
59
|
+
|
60
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
61
|
+
#
|
62
|
+
# This program is free software; you can redistribute it and/or modify
|
63
|
+
# it under the terms of the GNU General Public License as published by
|
64
|
+
# the Free Software Foundation; either version 2 of the License, or
|
65
|
+
# (at your option) any later version.
|
66
|
+
#
|
67
|
+
# This program is distributed in the hope that it will be useful,
|
68
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
69
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
70
|
+
# GNU General Public License for more details.
|
71
|
+
#
|
72
|
+
# You should have received a copy of the GNU General Public License
|
73
|
+
# along with this program; if not, write to the Free Software
|
74
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
data/script/perf_comp
ADDED
@@ -0,0 +1,151 @@
|
|
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 = (t1-t2==0) ? 1 : t1/t2
|
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
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
138
|
+
#
|
139
|
+
# This program is free software; you can redistribute it and/or modify
|
140
|
+
# it under the terms of the GNU General Public License as published by
|
141
|
+
# the Free Software Foundation; either version 2 of the License, or
|
142
|
+
# (at your option) any later version.
|
143
|
+
#
|
144
|
+
# This program is distributed in the hope that it will be useful,
|
145
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
146
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
147
|
+
# GNU General Public License for more details.
|
148
|
+
#
|
149
|
+
# You should have received a copy of the GNU General Public License
|
150
|
+
# along with this program; if not, write to the Free Software
|
151
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
data/script/perf_comp_gc
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
options = ""
|
4
|
+
if ARGV.length!=2
|
5
|
+
$stderr.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
|
+
$stderr.print "file #{fn} is unreadable\n"
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
rescue
|
20
|
+
$stderr.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
|
+
printf "\ngarbage per object type:\n"
|
89
|
+
printf "%-12s %9s %9s %9s %7s\n", "object type", "#c1", "#c2", "c2-c1", "c2/c1"
|
90
|
+
|
91
|
+
GCInfo.object_types(gcis).each do |object_type|
|
92
|
+
n1, n2 = gcis[0].garbage_totals[object_type], gcis[1].garbage_totals[object_type]
|
93
|
+
printf "%-12s %9d %9d %9d %7.2f\n", object_type, n1, n2, n2-n1, n2.to_f/n1
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
__END__
|
98
|
+
|
99
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
100
|
+
#
|
101
|
+
# This program is free software; you can redistribute it and/or modify
|
102
|
+
# it under the terms of the GNU General Public License as published by
|
103
|
+
# the Free Software Foundation; either version 2 of the License, or
|
104
|
+
# (at your option) any later version.
|
105
|
+
#
|
106
|
+
# This program is distributed in the hope that it will be useful,
|
107
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
108
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
109
|
+
# GNU General Public License for more details.
|
110
|
+
#
|
111
|
+
# You should have received a copy of the GNU General Public License
|
112
|
+
# along with this program; if not, write to the Free Software
|
113
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|