kamal-railsbench 0.9.9.pre
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/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
|