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.
Files changed (54) hide show
  1. data/BUGS +2 -0
  2. data/CHANGELOG +2124 -0
  3. data/GCPATCH +73 -0
  4. data/INSTALL +75 -0
  5. data/LICENSE +222 -0
  6. data/Manifest.txt +53 -0
  7. data/PROBLEMS +56 -0
  8. data/README +337 -0
  9. data/Rakefile +51 -0
  10. data/bin/railsbench +80 -0
  11. data/config/benchmarking.rb +21 -0
  12. data/config/benchmarks.rb +21 -0
  13. data/config/benchmarks.yml +2 -0
  14. data/images/empty.png +0 -0
  15. data/images/minus.png +0 -0
  16. data/images/plus.png +0 -0
  17. data/install.rb +70 -0
  18. data/latest_changes.txt +18 -0
  19. data/lib/benchmark.rb +576 -0
  20. data/lib/railsbench/benchmark.rb +576 -0
  21. data/lib/railsbench/benchmark_specs.rb +63 -0
  22. data/lib/railsbench/gc_info.rb +158 -0
  23. data/lib/railsbench/perf_info.rb +146 -0
  24. data/lib/railsbench/perf_utils.rb +202 -0
  25. data/lib/railsbench/railsbenchmark.rb +640 -0
  26. data/lib/railsbench/version.rb +9 -0
  27. data/lib/railsbench/write_headers_only.rb +15 -0
  28. data/postinstall.rb +12 -0
  29. data/ruby184gc.patch +516 -0
  30. data/ruby185gc.patch +562 -0
  31. data/ruby186gc.patch +564 -0
  32. data/ruby19gc.patch +2425 -0
  33. data/script/convert_raw_data_files +49 -0
  34. data/script/generate_benchmarks +171 -0
  35. data/script/perf_bench +74 -0
  36. data/script/perf_comp +151 -0
  37. data/script/perf_comp_gc +113 -0
  38. data/script/perf_diff +48 -0
  39. data/script/perf_diff_gc +53 -0
  40. data/script/perf_html +103 -0
  41. data/script/perf_plot +225 -0
  42. data/script/perf_plot_gc +254 -0
  43. data/script/perf_prof +87 -0
  44. data/script/perf_run +39 -0
  45. data/script/perf_run_gc +40 -0
  46. data/script/perf_table +104 -0
  47. data/script/perf_tex +58 -0
  48. data/script/perf_times +66 -0
  49. data/script/perf_times_gc +94 -0
  50. data/script/run_urls +57 -0
  51. data/setup.rb +1585 -0
  52. data/test/railsbench_test.rb +11 -0
  53. data/test/test_helper.rb +2 -0
  54. 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
@@ -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
@@ -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
@@ -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