railsbench 0.9.2 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1808 -451
- data/GCPATCH +73 -0
- data/INSTALL +5 -0
- data/Manifest.txt +23 -13
- data/PROBLEMS +0 -0
- data/README +23 -7
- data/Rakefile +1 -2
- data/bin/railsbench +7 -1
- data/config/benchmarking.rb +0 -0
- data/config/benchmarks.rb +3 -2
- data/config/benchmarks.yml +0 -0
- data/images/empty.png +0 -0
- data/images/minus.png +0 -0
- data/images/plus.png +0 -0
- data/install.rb +1 -1
- data/latest_changes.txt +18 -0
- data/lib/benchmark.rb +0 -0
- data/lib/railsbench/benchmark.rb +576 -0
- data/lib/railsbench/benchmark_specs.rb +63 -63
- data/lib/railsbench/gc_info.rb +38 -3
- data/lib/railsbench/perf_info.rb +1 -1
- data/lib/railsbench/perf_utils.rb +202 -179
- data/lib/railsbench/railsbenchmark.rb +213 -55
- data/lib/railsbench/version.rb +9 -9
- data/lib/railsbench/write_headers_only.rb +15 -15
- data/postinstall.rb +0 -0
- data/ruby185gc.patch +56 -29
- data/ruby186gc.patch +564 -0
- data/ruby19gc.patch +2425 -0
- data/script/convert_raw_data_files +49 -49
- data/script/generate_benchmarks +14 -4
- data/script/perf_bench +12 -8
- data/script/perf_comp +1 -1
- data/script/perf_comp_gc +9 -1
- data/script/perf_diff +2 -2
- data/script/perf_diff_gc +2 -2
- data/script/perf_html +1 -1
- data/script/perf_plot +192 -75
- data/script/perf_plot_gc +213 -74
- data/script/perf_prof +29 -10
- data/script/perf_run +2 -2
- data/script/perf_run_gc +2 -2
- data/script/perf_table +2 -2
- data/script/perf_tex +1 -1
- data/script/perf_times +6 -6
- data/script/perf_times_gc +14 -2
- data/script/run_urls +16 -10
- data/setup.rb +0 -0
- data/test/railsbench_test.rb +0 -0
- data/test/test_helper.rb +2 -0
- metadata +77 -55
data/script/perf_plot_gc
CHANGED
@@ -1,104 +1,243 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
require '
|
4
|
+
require 'optparse'
|
5
|
+
require 'ostruct'
|
5
6
|
|
6
7
|
$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
|
7
8
|
require 'railsbench/gc_info'
|
8
9
|
|
9
|
-
#
|
10
|
+
# parse options
|
11
|
+
o = OpenStruct.new
|
12
|
+
o.title = "GC Data Plot"
|
13
|
+
o.graph_width = '1400x1050'
|
14
|
+
o.font_size = 10
|
15
|
+
o.ignored_object_types = []
|
16
|
+
o.output_file = nil
|
17
|
+
o.plot_live = true
|
18
|
+
o.plot_freed = true
|
19
|
+
o.plot_type = :both
|
20
|
+
o.engine = :gruff
|
21
|
+
|
22
|
+
parser = OptionParser.new do |opts|
|
23
|
+
opts.banner = "Usage: perf_plot_gc [options] file1 file2 ..."
|
24
|
+
|
25
|
+
opts.separator ""
|
26
|
+
opts.separator "Options:"
|
27
|
+
|
28
|
+
opts.on("-t", "--title T",
|
29
|
+
"Specify the title for your plot") do |t|
|
30
|
+
o.title = t
|
31
|
+
end
|
10
32
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
labels = %w()
|
16
|
-
perf_data = []
|
17
|
-
graph_type = Gruff::StackedBar
|
18
|
-
graph_width = '1400x1050'
|
19
|
-
font_size = 14
|
20
|
-
ignored_object_types = %w(NODE STRING)
|
33
|
+
opts.on("-i", "--ignore LIST", Array,
|
34
|
+
"Specify the object types to ignore") do |i|
|
35
|
+
o.ignored_object_types = i.map{|t| t.upcase}
|
36
|
+
end
|
21
37
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
opts.on("-d", "--type TYPE", [:freed, :live, :both],
|
39
|
+
"Select data points to plot: (live, freed, both)") do |dp|
|
40
|
+
o.plot_type = dp
|
41
|
+
o.plot_freed = o.plot_live = false
|
42
|
+
case dp
|
43
|
+
when :live then o.plot_live = true
|
44
|
+
when :freed then o.plot_freed = true
|
45
|
+
when :both then o.plot_freed = true; o.plot_live = true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("-e", "--engine ENGINE", [:gruff, :gnuplot],
|
50
|
+
"Select plotting engine: (gruff, gnuplot)") do |e|
|
51
|
+
o.engine = e
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on("-f", "--font-size N", Integer,
|
55
|
+
"Overall font size to use in the plot (points)") do |n|
|
56
|
+
o.font_size = n
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on("-w", "--width W", Integer,
|
60
|
+
"Width of the plot (pixels)") do |w|
|
61
|
+
o.graph_width = w
|
43
62
|
end
|
63
|
+
|
64
|
+
opts.on("-g", "--geometry WxH", /\d+x\d+/,
|
65
|
+
"Specify plot dimensions (pixels)") do |d|
|
66
|
+
o.graph_width = d
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("-o", "--out FILE",
|
70
|
+
"Specify output file") do |f|
|
71
|
+
o.output_file = f
|
72
|
+
end
|
73
|
+
|
74
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
75
|
+
puts opts
|
76
|
+
exit
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# option compatibility with older versions
|
81
|
+
args=[]
|
82
|
+
ARGV.each do |arg|
|
83
|
+
arg = arg.sub("font_size", "font-size") if arg =~ /^-font_size/
|
84
|
+
arg = "-" + arg if arg =~ /^-(title|width|out|geometry|font-size|ignore)/
|
85
|
+
args << arg
|
44
86
|
end
|
45
87
|
|
46
|
-
|
88
|
+
parser.parse!(args)
|
89
|
+
|
90
|
+
o.output_file ||= if o.engine == :gruff
|
91
|
+
"graph.png"
|
92
|
+
elsif RUBY_PLATFORM =~ /darwin/
|
93
|
+
"graph.pdf"
|
94
|
+
else
|
95
|
+
"graph.ps"
|
96
|
+
end
|
97
|
+
o.files = []
|
98
|
+
o.names = []
|
99
|
+
args.each do |arg|
|
100
|
+
o.files << File.open_or_die(arg)
|
101
|
+
o.names[o.files.length-1] ||= File.basename(arg)
|
102
|
+
end
|
103
|
+
|
104
|
+
o.files.length > 0 or die(parser.banner)
|
47
105
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
gcis << GCInfo.new(file)
|
52
|
-
object_types.merge gcis.last.object_types
|
106
|
+
o.gcis = []
|
107
|
+
o.files.each do |file|
|
108
|
+
o.gcis << GCInfo.new(file)
|
53
109
|
file.close
|
54
110
|
end
|
55
111
|
|
56
|
-
object_types =
|
57
|
-
|
58
|
-
|
112
|
+
# o.object_types = %w(NODE STRING ARRAY HASH SCOPE VARMAP CLASS ICLASS REGEXP FLOAT MATCH FILE DATA MODULE OBJECT)
|
113
|
+
o.colors = %w(ff0000 00c000 0080ff c000ff 00eeee c04000 ee0000 2020c0 ffc020 008040 a080ff 804000 ff80ff 00c060 006080 c06080 008000 40ff80 306080 806000).map{|c| "#" + c}
|
114
|
+
o.object_types = GCInfo.object_types(o.gcis)
|
115
|
+
o.gc_count_max = o.gcis.map{|gci| gci.collections}.max
|
116
|
+
o.gc_max_processed = o.gcis.map{|gci| gci.processed_max}.max
|
117
|
+
o.gc_max_freed = o.gcis.map{|gci| gci.freed_max}.max
|
118
|
+
o.gc_max_live = o.gcis.map{|gci| gci.live_max}.max
|
119
|
+
|
120
|
+
o.title << " ["
|
121
|
+
o.title << "freed" if o.plot_freed
|
122
|
+
o.title << "," if o.plot_freed && o.plot_live
|
123
|
+
o.title << "live" if o.plot_live
|
124
|
+
o.title << "]"
|
125
|
+
o.title << " (ignoring #{o.ignored_object_types.join(', ')})" unless o.ignored_object_types.empty?
|
126
|
+
|
127
|
+
# for very large logs, we need to ignore some entries
|
128
|
+
N = o.gc_count_max < 100 ? 1 : o.gc_count_max / 99
|
129
|
+
|
130
|
+
class Plotter
|
131
|
+
attr_reader :o
|
132
|
+
def initialize(options)
|
133
|
+
@o = options
|
134
|
+
end
|
59
135
|
|
60
|
-
|
136
|
+
def plot_with_gruff
|
137
|
+
require 'gruff'
|
61
138
|
|
62
|
-
g.
|
63
|
-
g.add_color("#00FF00")
|
64
|
-
g.add_color("#0000FF")
|
139
|
+
g = Gruff::StackedBar.new(o.graph_width)
|
65
140
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
141
|
+
# on OS X, ImageMagick can't find it's default font (arial) sometimes, so specify some font
|
142
|
+
# g.font = 'Arial-Normal' if RUBY_PLATFORM =~ /darwin/
|
143
|
+
g.font = 'Helvetica-Narrow' if RUBY_PLATFORM =~ /darwin/
|
144
|
+
|
145
|
+
%w(#FF0000 #00FF00 #0000FF #D2FF77 #FF68C0 #D1FDFF #FFF0BD #15FFDC
|
146
|
+
).each do |color|
|
147
|
+
g.add_color(color)
|
148
|
+
end
|
70
149
|
|
71
|
-
g.title = title
|
72
|
-
g.sort = false
|
73
|
-
g.
|
74
|
-
g.
|
75
|
-
g.
|
76
|
-
|
77
|
-
|
78
|
-
g.
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
150
|
+
g.title = o.title
|
151
|
+
g.sort = false
|
152
|
+
g.title_font_size = o.font_size+2
|
153
|
+
g.legend_font_size = o.font_size-2
|
154
|
+
g.legend_box_size = o.font_size-2
|
155
|
+
g.marker_font_size = o.font_size-2
|
156
|
+
if o.ignored_object_types.empty?
|
157
|
+
g.minimum_value = 0
|
158
|
+
maximums = []
|
159
|
+
maximums << o.gc_max_live if o.plot_live
|
160
|
+
maximums << o.gc_max_freed if o.plot_freed
|
161
|
+
g.maximum_value = maximums.max
|
162
|
+
end
|
163
|
+
label_step = 0
|
164
|
+
label_step += 1 if o.plot_live
|
165
|
+
label_step += 1 if o.plot_freed
|
166
|
+
g.labels = Hash[* (0...o.gc_count_max).map{|i| [label_step*i*o.files.length, i.to_s]}.flatten ]
|
167
|
+
# puts g.labels.inspect
|
168
|
+
# puts object_types.inspect
|
169
|
+
puts "ignoring #{o.ignored_object_types.join(', ')}" unless o.ignored_object_types.empty?
|
170
|
+
|
171
|
+
(o.object_types + %w(FREELIST)).each do |ot|
|
172
|
+
data = prepare_data(ot)
|
173
|
+
# puts "#{ot}: #{data.inspect}"
|
174
|
+
g.data(ot, data)
|
90
175
|
end
|
176
|
+
|
177
|
+
g.write(o.output_file)
|
91
178
|
end
|
92
|
-
# puts "#{ot}: #{data.inspect}"
|
93
|
-
g.data(ot, data)
|
94
|
-
end
|
95
179
|
|
96
|
-
|
180
|
+
def prepare_data(ot)
|
181
|
+
return if o.ignored_object_types.include?(ot)
|
182
|
+
data = []
|
183
|
+
o.gc_count_max.times do |gc_index|
|
184
|
+
next unless 0 == gc_index.modulo(N)
|
185
|
+
for gci in o.gcis
|
186
|
+
map_at_this_gc = gci.freed_objects[gc_index].merge('FREELIST' => gci.freelist[gc_index])
|
187
|
+
data << ((map_at_this_gc && map_at_this_gc[ot]) || 0) if o.plot_freed
|
188
|
+
map_at_this_gc = gci.live_objects[gc_index]
|
189
|
+
data << ((map_at_this_gc && map_at_this_gc[ot]) || 0) if o.plot_live
|
190
|
+
end
|
191
|
+
end
|
192
|
+
data
|
193
|
+
end
|
194
|
+
|
195
|
+
def plot_with_gnuplot
|
196
|
+
require 'gnuplot'
|
197
|
+
# there's a separate gnuplot binary which can read from stdin, but the gem doesn't know this
|
198
|
+
ENV['RB_GNUPLOT'] ||= 'pgnuplot.exe' if RUBY_PLATFORM =~ /mswin/
|
199
|
+
plot = Gnuplot::Plot.new
|
200
|
+
if o.output_file =~ /\.pdf$/
|
201
|
+
plot.terminal "pdf enhanced color font 'Helvetica,4'"
|
202
|
+
else
|
203
|
+
plot.terminal "postscript enhanced color font 'Helvetica,4'"
|
204
|
+
end
|
205
|
+
plot.output o.output_file
|
206
|
+
plot.xlabel "Collections"
|
207
|
+
plot.ylabel "Objects"
|
208
|
+
plot.title o.title
|
209
|
+
plot.style "fill solid 1.0 noborder"
|
210
|
+
plot.style "data histogram"
|
211
|
+
plot.style "histogram rowstacked"
|
212
|
+
plot.xtics "out nomirror"
|
213
|
+
plot.xrange "[-1:#{(o.gc_count_max/N)*((o.plot_type == :both) ? 2 : 1)}]"
|
214
|
+
plot.key "outside invert reverse"
|
215
|
+
plot.boxwidth "0.8"
|
216
|
+
plot.grid "nopolar"
|
217
|
+
plot.grid "noxtics nomxtics ytics nomytics noztics nomztics nox2tics nomx2tics noy2tics nomy2tics nocbtics nomcbtics"
|
218
|
+
plot.grid "back linetype 0 linewidth 0.7"
|
219
|
+
|
220
|
+
(o.object_types + %w(FREELIST)).each_with_index do |ot, i|
|
221
|
+
next unless data = prepare_data(ot)
|
222
|
+
plot.data << Gnuplot::DataSet.new([[ot.downcase] + data]) do |ds|
|
223
|
+
ds.using = "1 title 1 lc rgb '#{ot == 'FREELIST' ? '#666666' : o.colors[i]}'"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
cmds = plot.to_gplot # puts cmds
|
228
|
+
Gnuplot.open(false){|gnuplot| gnuplot << cmds}
|
229
|
+
end
|
230
|
+
|
231
|
+
def plot
|
232
|
+
send "plot_with_#{o.engine}"
|
233
|
+
end
|
234
|
+
end
|
97
235
|
|
236
|
+
Plotter.new(o).plot
|
98
237
|
|
99
238
|
__END__
|
100
239
|
|
101
|
-
# Copyright (C) 2005
|
240
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
102
241
|
#
|
103
242
|
# This program is free software; you can redistribute it and/or modify
|
104
243
|
# it under the terms of the GNU General Public License as published by
|
data/script/perf_prof
CHANGED
@@ -9,6 +9,8 @@ end
|
|
9
9
|
bindir = File.dirname(__FILE__)
|
10
10
|
require "#{bindir}/../lib/railsbench/perf_utils"
|
11
11
|
|
12
|
+
determine_rails_root_or_die!
|
13
|
+
|
12
14
|
perf_data_dir = (ENV['RAILS_PERF_DATA'] ||= ENV['HOME'])
|
13
15
|
|
14
16
|
iterations = ARGV[0]
|
@@ -16,20 +18,32 @@ options = ARGV[1]
|
|
16
18
|
config = ARGV[2]
|
17
19
|
benchmark = ""
|
18
20
|
|
19
|
-
ruby_prof_opts="-ruby_prof=1"
|
21
|
+
ruby_prof_opts="-ruby_prof=0.1/1"
|
20
22
|
warmup="-warmup"
|
21
23
|
|
22
24
|
warmup = "" if options =~ /-warmup/
|
23
25
|
benchmark = $1 if options =~ /-bm=([^ ]+)/
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
if options =~ /(-ruby_prof=[^ ]+)/
|
27
|
+
ruby_prof_opts = $1
|
28
|
+
options = options.sub($1, '')
|
29
|
+
end
|
30
|
+
profile_type = 'graph'
|
31
|
+
if options =~ /(-profile_type=([^ ]+))/
|
32
|
+
profile_type = $2
|
33
|
+
ruby_prof_opts << " " << $1
|
34
|
+
options = options.sub($1, '')
|
35
|
+
end
|
36
|
+
extension = case profile_type
|
37
|
+
when 'grind' then 'dat'
|
38
|
+
when 'flat' then 'txt'
|
39
|
+
else 'html'
|
40
|
+
end
|
27
41
|
date = Time.now.strftime '%m-%d'
|
28
42
|
|
29
43
|
if config
|
30
|
-
benchmark_file="#{perf_data_dir}/#{date}.#{benchmark}.#{config}
|
44
|
+
benchmark_file="#{perf_data_dir}/#{date}.#{benchmark}.#{config}.#{profile_type}.#{extension}"
|
31
45
|
else
|
32
|
-
benchmark_file="#{perf_data_dir}/perf_run.#{benchmark}
|
46
|
+
benchmark_file="#{perf_data_dir}/perf_run.#{benchmark}.#{profile_type}.#{extension}"
|
33
47
|
end
|
34
48
|
ENV['RAILS_BENCHMARK_FILE'] = benchmark_file
|
35
49
|
|
@@ -42,16 +56,21 @@ perf_options="#{iterations} #{options} #{warmup} #{ruby_prof_opts}"
|
|
42
56
|
perf_cmd = "ruby #{bindir}/run_urls #{perf_options} >#{null}"
|
43
57
|
system(perf_cmd) || die("perf_prof: #{perf_cmd} returned #{$?}")
|
44
58
|
|
59
|
+
benchmark_file.sub!('.multi.', '.stack.') if profile_type == 'multi'
|
45
60
|
puts "profile data written to #{benchmark_file}"
|
46
61
|
|
47
|
-
|
48
|
-
|
49
|
-
|
62
|
+
if profile_type == 'grind'
|
63
|
+
system("kcachegrind #{benchmark_file} 2>/dev/null &") unless RUBY_PLATFORM =~ /win32/
|
64
|
+
else
|
65
|
+
case RUBY_PLATFORM
|
66
|
+
when /win32/ then system("start #{benchmark_file.gsub(/\//, '\\')}")
|
67
|
+
when /darwin/ then system("osascript -e 'tell application \"Safari\" to open location \"#{benchmark_file}\"'")
|
68
|
+
end
|
50
69
|
end
|
51
70
|
|
52
71
|
__END__
|
53
72
|
|
54
|
-
# Copyright (C) 2005
|
73
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
55
74
|
#
|
56
75
|
# This program is free software; you can redistribute it and/or modify
|
57
76
|
# it under the terms of the GNU General Public License as published by
|
data/script/perf_run
CHANGED
@@ -9,7 +9,7 @@ end
|
|
9
9
|
bindir = File.dirname(__FILE__)
|
10
10
|
require "#{bindir}/../lib/railsbench/perf_utils"
|
11
11
|
|
12
|
-
|
12
|
+
determine_rails_root_or_die!
|
13
13
|
|
14
14
|
iterations = ARGV[0]
|
15
15
|
options = ARGV[1]
|
@@ -22,7 +22,7 @@ perf_run("perf_run", iterations, options, benchmark_file)
|
|
22
22
|
|
23
23
|
__END__
|
24
24
|
|
25
|
-
# Copyright (C) 2005
|
25
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
26
26
|
#
|
27
27
|
# This program is free software; you can redistribute it and/or modify
|
28
28
|
# it under the terms of the GNU General Public License as published by
|
data/script/perf_run_gc
CHANGED
@@ -9,7 +9,7 @@ end
|
|
9
9
|
bindir = File.dirname(__FILE__)
|
10
10
|
require "#{bindir}/../lib/railsbench/perf_utils"
|
11
11
|
|
12
|
-
|
12
|
+
determine_rails_root_or_die!
|
13
13
|
|
14
14
|
iterations = ARGV[0]
|
15
15
|
options = ARGV[1]
|
@@ -23,7 +23,7 @@ perf_run_gc("perf_run_gc", iterations, options, benchmark_file)
|
|
23
23
|
|
24
24
|
__END__
|
25
25
|
|
26
|
-
# Copyright (C) 2005
|
26
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
27
27
|
#
|
28
28
|
# This program is free software; you can redistribute it and/or modify
|
29
29
|
# it under the terms of the GNU General Public License as published by
|
data/script/perf_table
CHANGED
@@ -67,7 +67,7 @@ perf_data = perf_data.map{|d| d.restrict_to(selection.map{|i| i-1})}
|
|
67
67
|
#puts labels.inspect
|
68
68
|
#puts perf_data.length
|
69
69
|
#puts perf_data.inspect
|
70
|
-
#puts names.inspect
|
70
|
+
#puts names.inspect
|
71
71
|
|
72
72
|
# puts labels.zip(perf_data).inspect
|
73
73
|
puts "<table border=1>"
|
@@ -87,7 +87,7 @@ puts "</table>"
|
|
87
87
|
|
88
88
|
__END__
|
89
89
|
|
90
|
-
# Copyright (C) 2007 Stefan Kaes
|
90
|
+
# Copyright (C) 2007, 2008 Stefan Kaes
|
91
91
|
#
|
92
92
|
# This program is free software; you can redistribute it and/or modify
|
93
93
|
# it under the terms of the GNU General Public License as published by
|
data/script/perf_tex
CHANGED
@@ -41,7 +41,7 @@ end
|
|
41
41
|
|
42
42
|
__END__
|
43
43
|
|
44
|
-
# Copyright (C) 2005
|
44
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
45
45
|
#
|
46
46
|
# This program is free software; you can redistribute it and/or modify
|
47
47
|
# it under the terms of the GNU General Public License as published by
|