ruby-prof 0.11.2 → 0.11.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/Rakefile +5 -0
- data/bin/ruby-prof +60 -60
- data/ext/ruby_prof/rp_stack.c +9 -9
- data/ext/ruby_prof/rp_stack.h +9 -9
- data/ext/ruby_prof/rp_thread.c +4 -4
- data/ext/ruby_prof/ruby_prof.c +12 -12
- data/ext/ruby_prof/version.h +1 -1
- data/lib/ruby-prof/compatibility.rb +7 -2
- data/lib/ruby-prof/printers/dot_printer.rb +1 -1
- data/lib/ruby-prof/printers/graph_html_printer.rb +0 -1
- data/lib/ruby-prof/profile.rb +1 -1
- data/lib/ruby-prof/rack.rb +0 -5
- data/test/measure_process_time_test.rb +2 -2
- data/test/pause_test.rb +5 -5
- data/test/prime.rb +1 -1
- data/test/printers_test.rb +2 -0
- data/test/recursive_test.rb +2 -2
- metadata +2 -5
- data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +0 -108
- data/test/bug_test.rb +0 -6
- data/test/gc_test.rb +0 -35
data/README.rdoc
CHANGED
@@ -15,7 +15,7 @@ ruby-prof is a fast code profiler for Ruby. Its features include:
|
|
15
15
|
|
16
16
|
== Requirements
|
17
17
|
|
18
|
-
ruby-prof requires Ruby 1.8.7 or 1.9.
|
18
|
+
ruby-prof requires Ruby 1.8.7 or 1.9.2 and higher.
|
19
19
|
|
20
20
|
If you are running Linux or Unix you'll need a C compiler so the extension
|
21
21
|
can be compiled when it is installed.
|
data/Rakefile
CHANGED
@@ -5,6 +5,7 @@ require "rake/extensiontask"
|
|
5
5
|
require "rake/testtask"
|
6
6
|
require "rdoc/task"
|
7
7
|
require "date"
|
8
|
+
require 'rake/clean'
|
8
9
|
|
9
10
|
# To release a version of ruby-prof:
|
10
11
|
# * Update version.h
|
@@ -78,6 +79,10 @@ end
|
|
78
79
|
|
79
80
|
task :default => :package
|
80
81
|
|
82
|
+
for file in Dir['**/*.so']
|
83
|
+
CLEAN.include file
|
84
|
+
end
|
85
|
+
|
81
86
|
desc 'Run the ruby-prof test suite'
|
82
87
|
Rake::TestTask.new do |t|
|
83
88
|
t.libs += %w(lib ext test)
|
data/bin/ruby-prof
CHANGED
@@ -17,13 +17,13 @@ require 'ostruct'
|
|
17
17
|
require 'optparse'
|
18
18
|
require File.expand_path('../../lib/ruby-prof', __FILE__)
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
20
|
+
rubyprof_options = OpenStruct.new
|
21
|
+
rubyprof_options.measure_mode = RubyProf::PROCESS_TIME
|
22
|
+
rubyprof_options.printer = RubyProf::FlatPrinter
|
23
|
+
rubyprof_options.min_percent = 0
|
24
|
+
rubyprof_options.file = nil
|
25
|
+
rubyprof_options.replace_prog_name = false
|
26
|
+
rubyprof_options.specialized_instruction = false
|
27
27
|
|
28
28
|
opts = OptionParser.new do |opts|
|
29
29
|
opts.banner = "ruby_prof #{RubyProf::VERSION}\n" +
|
@@ -47,19 +47,19 @@ opts = OptionParser.new do |opts|
|
|
47
47
|
|
48
48
|
case printer
|
49
49
|
when :flat
|
50
|
-
|
50
|
+
rubyprof_options.printer = RubyProf::FlatPrinter
|
51
51
|
when :flat_with_line_numbers
|
52
|
-
|
52
|
+
rubyprof_options.printer = RubyProf::FlatPrinterWithLineNumbers
|
53
53
|
when :graph
|
54
|
-
|
54
|
+
rubyprof_options.printer = RubyProf::GraphPrinter
|
55
55
|
when :graph_html
|
56
|
-
|
56
|
+
rubyprof_options.printer = RubyProf::GraphHtmlPrinter
|
57
57
|
when :call_tree
|
58
|
-
|
58
|
+
rubyprof_options.printer = RubyProf::CallTreePrinter
|
59
59
|
when :call_stack
|
60
|
-
|
60
|
+
rubyprof_options.printer = RubyProf::CallStackPrinter
|
61
61
|
when :dot
|
62
|
-
|
62
|
+
rubyprof_options.printer = RubyProf::DotPrinter
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -67,13 +67,13 @@ opts = OptionParser.new do |opts|
|
|
67
67
|
'The minimum percent a method must take before ',
|
68
68
|
' being included in output reports.',
|
69
69
|
' this option is not supported for call tree.') do |min_percent|
|
70
|
-
|
70
|
+
rubyprof_options.min_percent = min_percent
|
71
71
|
end
|
72
72
|
|
73
73
|
opts.on('-f path', '--file=path',
|
74
74
|
'Output results to a file instead of standard out.') do |file|
|
75
|
-
|
76
|
-
|
75
|
+
rubyprof_options.file = file
|
76
|
+
rubyprof_options.old_wd = Dir.pwd
|
77
77
|
end
|
78
78
|
|
79
79
|
opts.on('--mode=measure_mode',
|
@@ -89,19 +89,19 @@ opts = OptionParser.new do |opts|
|
|
89
89
|
|
90
90
|
case measure_mode
|
91
91
|
when :process
|
92
|
-
|
92
|
+
rubyprof_options.measure_mode = RubyProf::PROCESS_TIME
|
93
93
|
when :wall
|
94
|
-
|
94
|
+
rubyprof_options.measure_mode = RubyProf::WALL_TIME
|
95
95
|
when :cpu
|
96
|
-
|
96
|
+
rubyprof_options.measure_mode = RubyProf::CPU_TIME
|
97
97
|
when :allocations
|
98
|
-
|
98
|
+
rubyprof_options.measure_mode = RubyProf::ALLOCATIONS
|
99
99
|
when :memory
|
100
|
-
|
100
|
+
rubyprof_options.measure_mode = RubyProf::MEMORY
|
101
101
|
when :gc_runs
|
102
|
-
|
102
|
+
rubyprof_options.measure_mode = RubyProf::GC_RUNS
|
103
103
|
when :gc_time
|
104
|
-
|
104
|
+
rubyprof_options.measure_mode = RubyProf::GC_TIME
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
@@ -112,7 +112,7 @@ opts = OptionParser.new do |opts|
|
|
112
112
|
' wait - Wait time',
|
113
113
|
' child - Child time') do |sort_mode|
|
114
114
|
|
115
|
-
|
115
|
+
rubyprof_options.sort_method = case sort_mode
|
116
116
|
when :total
|
117
117
|
:total_time
|
118
118
|
when :self
|
@@ -125,12 +125,12 @@ opts = OptionParser.new do |opts|
|
|
125
125
|
end
|
126
126
|
|
127
127
|
opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
|
128
|
-
|
128
|
+
rubyprof_options.replace_prog_name = true
|
129
129
|
end
|
130
130
|
|
131
131
|
if defined?(VM)
|
132
132
|
opts.on("--specialized-instruction", "Turn on specified instruction.") do
|
133
|
-
|
133
|
+
rubyprof_options.specialized_instruction = true
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
@@ -154,38 +154,38 @@ opts = OptionParser.new do |opts|
|
|
154
154
|
end
|
155
155
|
|
156
156
|
opts.on('-R lib', '--require-noprof lib', 'require a specific library (not profiled)') do |lib|
|
157
|
-
|
158
|
-
|
157
|
+
rubyprof_options.pre_libs ||= []
|
158
|
+
rubyprof_options.pre_libs << lib
|
159
159
|
end
|
160
160
|
|
161
161
|
opts.on('-E code', '--eval-noprof code', 'execute the ruby statements (not profiled)') do |code|
|
162
|
-
|
163
|
-
|
162
|
+
rubyprof_options.pre_exec ||= []
|
163
|
+
rubyprof_options.pre_exec << code
|
164
164
|
end
|
165
165
|
|
166
166
|
opts.on('-r lib', '--require lib', 'require a specific library') do |lib|
|
167
|
-
|
168
|
-
|
167
|
+
rubyprof_options.libs ||= []
|
168
|
+
rubyprof_options.libs << lib
|
169
169
|
end
|
170
170
|
|
171
171
|
opts.on('-e code', '--eval', 'execute the ruby statements') do |code|
|
172
|
-
|
173
|
-
|
172
|
+
rubyprof_options.exec ||= []
|
173
|
+
rubyprof_options.exec << code
|
174
174
|
end
|
175
175
|
|
176
176
|
opts.on('-x regexp', '--exclude regexp', 'exclude methods by regexp (see method elimination)') do|meth|
|
177
|
-
|
178
|
-
|
177
|
+
rubyprof_options.eliminate_methods ||= []
|
178
|
+
rubyprof_options.eliminate_methods << Regexp.new(meth)
|
179
179
|
end
|
180
180
|
|
181
181
|
opts.on('-X file', '--exclude-file file', 'exclude methods by regexp listed in file (see method elimination)') do|file|
|
182
|
-
|
183
|
-
|
182
|
+
rubyprof_options.eliminate_methods_files ||= []
|
183
|
+
rubyprof_options.eliminate_methods_files << file
|
184
184
|
end
|
185
185
|
|
186
186
|
opts.on('--exclude-common-cycles', 'make common iterators like Integer#times appear inlined') do|meth|
|
187
|
-
|
188
|
-
|
187
|
+
rubyprof_options.eliminate_methods ||= []
|
188
|
+
rubyprof_options.eliminate_methods += %w{
|
189
189
|
Integer#times
|
190
190
|
Integer#upto
|
191
191
|
Integer#downto
|
@@ -218,8 +218,8 @@ opts = OptionParser.new do |opts|
|
|
218
218
|
end
|
219
219
|
|
220
220
|
opts.on('--exclude-common-callbacks', 'make common callbacks invocations like Integer#times appear inlined so you can see call origins in graph') do|meth|
|
221
|
-
|
222
|
-
|
221
|
+
rubyprof_options.eliminate_methods ||= []
|
222
|
+
rubyprof_options.eliminate_methods += %w{
|
223
223
|
Method#call
|
224
224
|
Proc#call
|
225
225
|
ActiveSupport::Callbacks::ClassMethods#__run_callback
|
@@ -238,7 +238,7 @@ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument,
|
|
238
238
|
end
|
239
239
|
|
240
240
|
# Make sure the user specified at least one file
|
241
|
-
if ARGV.length < 1 and not
|
241
|
+
if ARGV.length < 1 and not rubyprof_options.exec
|
242
242
|
puts opts
|
243
243
|
puts ""
|
244
244
|
puts "Must specify a script to run"
|
@@ -255,18 +255,18 @@ at_exit {
|
|
255
255
|
result = RubyProf.stop
|
256
256
|
|
257
257
|
# Eliminate unwanted methods from call graph
|
258
|
-
result.eliminate_methods!
|
259
|
-
|
258
|
+
result.eliminate_methods! rubyprof_options.eliminate_methods if rubyprof_options.eliminate_methods
|
259
|
+
rubyprof_options.eliminate_methods_files.each{|f| result.eliminate_methods!(f)} if rubyprof_options.eliminate_methods_files
|
260
260
|
|
261
261
|
# Create a printer
|
262
|
-
printer =
|
263
|
-
printer_options = {:min_percent =>
|
262
|
+
printer = rubyprof_options.printer.new(result)
|
263
|
+
printer_options = {:min_percent => rubyprof_options.min_percent, :sort_method => rubyprof_options.sort_method}
|
264
264
|
|
265
265
|
# Get output
|
266
|
-
if
|
266
|
+
if rubyprof_options.file
|
267
267
|
# write it relative to the dir they *started* in, as it's a bit surprising to write it in the dir they end up in.
|
268
|
-
Dir.chdir(
|
269
|
-
File.open(
|
268
|
+
Dir.chdir(rubyprof_options.old_wd) do
|
269
|
+
File.open(rubyprof_options.file, 'w') do |file|
|
270
270
|
printer.print(file, printer_options)
|
271
271
|
end
|
272
272
|
end
|
@@ -277,33 +277,33 @@ at_exit {
|
|
277
277
|
}
|
278
278
|
|
279
279
|
# Now set measure mode
|
280
|
-
RubyProf.measure_mode =
|
280
|
+
RubyProf.measure_mode = rubyprof_options.measure_mode
|
281
281
|
|
282
282
|
# Set VM compile option
|
283
283
|
if defined?(VM)
|
284
284
|
VM::InstructionSequence.compile_option = {
|
285
285
|
:trace_instruction => true,
|
286
|
-
:specialized_instruction =>
|
286
|
+
:specialized_instruction => rubyprof_options.specialized_instruction
|
287
287
|
}
|
288
288
|
end
|
289
289
|
|
290
290
|
# Get the script we will execute
|
291
291
|
script = ARGV.shift
|
292
|
-
if
|
292
|
+
if rubyprof_options.replace_prog_name
|
293
293
|
$0 = File.expand_path(script)
|
294
294
|
end
|
295
295
|
|
296
|
-
if
|
297
|
-
|
296
|
+
if rubyprof_options.pre_libs
|
297
|
+
rubyprof_options.pre_libs.each { |l| require l }
|
298
298
|
end
|
299
299
|
|
300
|
-
if
|
301
|
-
|
300
|
+
if rubyprof_options.pre_exec
|
301
|
+
rubyprof_options.pre_exec.each { |c| eval c }
|
302
302
|
end
|
303
303
|
|
304
304
|
# do not pollute profiling report with OpenStruct#libs
|
305
|
-
ol =
|
306
|
-
oe =
|
305
|
+
ol = rubyprof_options.libs
|
306
|
+
oe = rubyprof_options.exec
|
307
307
|
|
308
308
|
# Start profiling
|
309
309
|
RubyProf.start
|
data/ext/ruby_prof/rp_stack.c
CHANGED
@@ -6,16 +6,16 @@
|
|
6
6
|
#define INITIAL_STACK_SIZE 8
|
7
7
|
|
8
8
|
void
|
9
|
-
|
9
|
+
prof_frame_pause(prof_frame_t *frame, double current_measurement)
|
10
10
|
{
|
11
|
-
if (frame &&
|
11
|
+
if (frame && prof_frame_is_unpaused(frame))
|
12
12
|
frame->pause_time = current_measurement;
|
13
13
|
}
|
14
14
|
|
15
15
|
void
|
16
|
-
|
16
|
+
prof_frame_unpause(prof_frame_t *frame, double current_measurement)
|
17
17
|
{
|
18
|
-
if (frame &&
|
18
|
+
if (frame && prof_frame_is_paused(frame)) {
|
19
19
|
frame->dead_time += (current_measurement - frame->pause_time);
|
20
20
|
frame->pause_time = -1;
|
21
21
|
}
|
@@ -25,7 +25,7 @@ frame_unpause(prof_frame_t *frame, double current_measurement)
|
|
25
25
|
/* Creates a stack of prof_frame_t to keep track
|
26
26
|
of timings for active methods. */
|
27
27
|
prof_stack_t *
|
28
|
-
|
28
|
+
prof_stack_create()
|
29
29
|
{
|
30
30
|
prof_stack_t *stack = ALLOC(prof_stack_t);
|
31
31
|
stack->start = ALLOC_N(prof_frame_t, INITIAL_STACK_SIZE);
|
@@ -36,14 +36,14 @@ stack_create()
|
|
36
36
|
}
|
37
37
|
|
38
38
|
void
|
39
|
-
|
39
|
+
prof_stack_free(prof_stack_t *stack)
|
40
40
|
{
|
41
41
|
xfree(stack->start);
|
42
42
|
xfree(stack);
|
43
43
|
}
|
44
44
|
|
45
45
|
prof_frame_t *
|
46
|
-
|
46
|
+
prof_stack_push(prof_stack_t *stack)
|
47
47
|
{
|
48
48
|
prof_frame_t* result = NULL;
|
49
49
|
|
@@ -74,7 +74,7 @@ stack_push(prof_stack_t *stack)
|
|
74
74
|
}
|
75
75
|
|
76
76
|
prof_frame_t *
|
77
|
-
|
77
|
+
prof_stack_pop(prof_stack_t *stack)
|
78
78
|
{
|
79
79
|
if (stack->ptr == stack->start)
|
80
80
|
return NULL;
|
@@ -83,7 +83,7 @@ stack_pop(prof_stack_t *stack)
|
|
83
83
|
}
|
84
84
|
|
85
85
|
prof_frame_t *
|
86
|
-
|
86
|
+
prof_stack_peek(prof_stack_t *stack)
|
87
87
|
{
|
88
88
|
if (stack->ptr == stack->start)
|
89
89
|
return NULL;
|
data/ext/ruby_prof/rp_stack.h
CHANGED
@@ -28,10 +28,10 @@ typedef struct
|
|
28
28
|
unsigned int line;
|
29
29
|
} prof_frame_t;
|
30
30
|
|
31
|
-
#define
|
32
|
-
#define
|
33
|
-
void
|
34
|
-
void
|
31
|
+
#define prof_frame_is_paused(f) (f->pause_time >= 0)
|
32
|
+
#define prof_frame_is_unpaused(f) (f->pause_time < 0)
|
33
|
+
void prof_frame_pause(prof_frame_t*, double current_measurement);
|
34
|
+
void prof_frame_unpause(prof_frame_t*, double current_measurement);
|
35
35
|
|
36
36
|
|
37
37
|
/* Current stack of active methods.*/
|
@@ -42,10 +42,10 @@ typedef struct
|
|
42
42
|
prof_frame_t *ptr;
|
43
43
|
} prof_stack_t;
|
44
44
|
|
45
|
-
prof_stack_t *
|
46
|
-
void
|
47
|
-
prof_frame_t *
|
48
|
-
prof_frame_t *
|
49
|
-
prof_frame_t *
|
45
|
+
prof_stack_t * prof_stack_create();
|
46
|
+
void prof_stack_free(prof_stack_t *stack);
|
47
|
+
prof_frame_t * prof_stack_push(prof_stack_t *stack);
|
48
|
+
prof_frame_t * prof_stack_pop(prof_stack_t *stack);
|
49
|
+
prof_frame_t * prof_stack_peek(prof_stack_t *stack);
|
50
50
|
|
51
51
|
#endif //__RP_STACK__
|
data/ext/ruby_prof/rp_thread.c
CHANGED
@@ -10,7 +10,7 @@ thread_data_t*
|
|
10
10
|
thread_data_create()
|
11
11
|
{
|
12
12
|
thread_data_t* result = ALLOC(thread_data_t);
|
13
|
-
result->stack =
|
13
|
+
result->stack = prof_stack_create();
|
14
14
|
result->method_table = method_table_create();
|
15
15
|
result->top = NULL;
|
16
16
|
result->object = Qnil;
|
@@ -44,7 +44,7 @@ thread_data_free(thread_data_t* thread_data)
|
|
44
44
|
thread_data_ruby_gc_free(thread_data);
|
45
45
|
thread_data->top = NULL;
|
46
46
|
method_table_free(thread_data->method_table);
|
47
|
-
|
47
|
+
prof_stack_free(thread_data->stack);
|
48
48
|
|
49
49
|
thread_data->thread_id = Qnil;
|
50
50
|
|
@@ -157,7 +157,7 @@ switch_thread(void* prof, VALUE thread_id)
|
|
157
157
|
thread_data_t *thread_data = threads_table_lookup(profile, thread_id);
|
158
158
|
|
159
159
|
/* Get current frame for this thread */
|
160
|
-
prof_frame_t *frame =
|
160
|
+
prof_frame_t *frame = prof_stack_peek(thread_data->stack);
|
161
161
|
|
162
162
|
/* Update the time this thread waited for another thread */
|
163
163
|
if (frame)
|
@@ -170,7 +170,7 @@ switch_thread(void* prof, VALUE thread_id)
|
|
170
170
|
and reset this thread's last context switch to 0.*/
|
171
171
|
if (profile->last_thread_data)
|
172
172
|
{
|
173
|
-
prof_frame_t *last_frame =
|
173
|
+
prof_frame_t *last_frame = prof_stack_peek(profile->last_thread_data->stack);
|
174
174
|
if (last_frame)
|
175
175
|
last_frame->switch_time = measurement;
|
176
176
|
}
|
data/ext/ruby_prof/ruby_prof.c
CHANGED
@@ -139,7 +139,7 @@ pop_frame(prof_profile_t* profile, thread_data_t *thread_data)
|
|
139
139
|
_Bool frame_paused;
|
140
140
|
#endif
|
141
141
|
|
142
|
-
frame =
|
142
|
+
frame = prof_stack_pop(thread_data->stack); // only time it's called
|
143
143
|
|
144
144
|
/* Frame can be null. This can happen if RubProf.start is called from
|
145
145
|
a method that exits. And it can happen if an exception is raised
|
@@ -149,8 +149,8 @@ pop_frame(prof_profile_t* profile, thread_data_t *thread_data)
|
|
149
149
|
return NULL;
|
150
150
|
|
151
151
|
/* Calculate the total time this method took */
|
152
|
-
frame_paused =
|
153
|
-
|
152
|
+
frame_paused = prof_frame_is_paused(frame);
|
153
|
+
prof_frame_unpause(frame, measurement);
|
154
154
|
total_time = measurement - frame->start_time - frame->dead_time;
|
155
155
|
self_time = total_time - frame->child_time - frame->wait_time;
|
156
156
|
|
@@ -161,7 +161,7 @@ pop_frame(prof_profile_t* profile, thread_data_t *thread_data)
|
|
161
161
|
call_info->self_time += self_time;
|
162
162
|
call_info->wait_time += frame->wait_time;
|
163
163
|
|
164
|
-
parent_frame =
|
164
|
+
parent_frame = prof_stack_peek(thread_data->stack);
|
165
165
|
if (parent_frame)
|
166
166
|
{
|
167
167
|
parent_frame->child_time += total_time;
|
@@ -169,7 +169,7 @@ pop_frame(prof_profile_t* profile, thread_data_t *thread_data)
|
|
169
169
|
|
170
170
|
// Repause parent if currently paused
|
171
171
|
if (frame_paused)
|
172
|
-
|
172
|
+
prof_frame_pause(parent_frame, measurement);
|
173
173
|
|
174
174
|
call_info->line = parent_frame->line;
|
175
175
|
}
|
@@ -298,7 +298,7 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
298
298
|
thread_data = profile->last_thread_data;
|
299
299
|
|
300
300
|
/* Get the current frame for the current thread. */
|
301
|
-
frame =
|
301
|
+
frame = prof_stack_peek(thread_data->stack);
|
302
302
|
|
303
303
|
switch (event) {
|
304
304
|
case RUBY_EVENT_LINE:
|
@@ -350,11 +350,11 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
350
350
|
// Unpause the parent frame. If currently paused then:
|
351
351
|
// 1) The child frame will begin paused.
|
352
352
|
// 2) The parent will inherit the child's dead time.
|
353
|
-
|
353
|
+
prof_frame_unpause(frame, measurement);
|
354
354
|
}
|
355
355
|
|
356
356
|
/* Push a new frame onto the stack for a new c-call or ruby call (into a method) */
|
357
|
-
frame =
|
357
|
+
frame = prof_stack_push(thread_data->stack);
|
358
358
|
frame->call_info = call_info;
|
359
359
|
frame->call_info->depth = frame->depth;
|
360
360
|
frame->start_time = measurement;
|
@@ -522,8 +522,8 @@ static int pause_thread(st_data_t key, st_data_t value, st_data_t data)
|
|
522
522
|
thread_data_t* thread_data = (thread_data_t *) value;
|
523
523
|
prof_profile_t* profile = (prof_profile_t*) data;
|
524
524
|
|
525
|
-
prof_frame_t* frame =
|
526
|
-
|
525
|
+
prof_frame_t* frame = prof_stack_peek(thread_data->stack);
|
526
|
+
prof_frame_pause(frame, profile->measurement_at_pause_resume);
|
527
527
|
|
528
528
|
return ST_CONTINUE;
|
529
529
|
}
|
@@ -533,8 +533,8 @@ static int unpause_thread(st_data_t key, st_data_t value, st_data_t data)
|
|
533
533
|
thread_data_t* thread_data = (thread_data_t *) value;
|
534
534
|
prof_profile_t* profile = (prof_profile_t*) data;
|
535
535
|
|
536
|
-
prof_frame_t* frame =
|
537
|
-
|
536
|
+
prof_frame_t* frame = prof_stack_peek(thread_data->stack);
|
537
|
+
prof_frame_unpause(frame, profile->measurement_at_pause_resume);
|
538
538
|
|
539
539
|
return ST_CONTINUE;
|
540
540
|
}
|
data/ext/ruby_prof/version.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/* Copyright (C) 2005-2011 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
2
|
Please see the LICENSE file for copyright and distribution information */
|
3
3
|
|
4
|
-
#define RUBY_PROF_VERSION "0.11.
|
4
|
+
#define RUBY_PROF_VERSION "0.11.3" // as a string, for easy parsing from rake files
|
5
5
|
#define RUBY_PROF_VERSION_MAJ 0
|
6
6
|
#define RUBY_PROF_VERSION_MIN 11
|
7
7
|
#define RUBY_PROF_VERSION_MIC 2
|
@@ -73,14 +73,19 @@ module RubyProf
|
|
73
73
|
end
|
74
74
|
|
75
75
|
# call-seq:
|
76
|
-
# exclude_threads
|
76
|
+
# exclude_threads -> exclude_threads
|
77
77
|
#
|
78
|
-
#
|
78
|
+
# Returns threads ruby-prof should exclude from profiling
|
79
79
|
|
80
80
|
def self.exclude_threads
|
81
81
|
@exclude_threads ||= Array.new
|
82
82
|
end
|
83
83
|
|
84
|
+
# call-seq:
|
85
|
+
# exclude_threads= -> void
|
86
|
+
#
|
87
|
+
# Specifies what threads ruby-prof should exclude from profiling
|
88
|
+
|
84
89
|
def self.exclude_threads=(value)
|
85
90
|
@exclude_threads = value
|
86
91
|
end
|
@@ -96,7 +96,7 @@ module RubyProf
|
|
96
96
|
thread.methods.each{|m| grouped[m.klass_name] ||= []; grouped[m.klass_name] << m}
|
97
97
|
grouped.each do |cls, methods2|
|
98
98
|
# Filter down to just seen methods
|
99
|
-
big_methods
|
99
|
+
big_methods = methods2.select{|m| @seen_methods.include? m}
|
100
100
|
|
101
101
|
if !big_methods.empty?
|
102
102
|
puts "subgraph cluster_#{cls.object_id} {"
|
data/lib/ruby-prof/profile.rb
CHANGED
@@ -49,7 +49,7 @@ module RubyProf
|
|
49
49
|
# read regexps from file
|
50
50
|
def read_regexps_from_file(file_name)
|
51
51
|
matchers = []
|
52
|
-
File.open(
|
52
|
+
File.open(file_name).each_line do |l|
|
53
53
|
next if (l =~ /^(#.*|\s*)$/) # emtpy lines and lines starting with #
|
54
54
|
matchers << Regexp.new(l.strip)
|
55
55
|
end
|
data/lib/ruby-prof/rack.rb
CHANGED
@@ -13,11 +13,6 @@ module Rack
|
|
13
13
|
::RubyProf::GraphHtmlPrinter => 'graph.html',
|
14
14
|
::RubyProf::CallStackPrinter => 'call_stack.html'}
|
15
15
|
|
16
|
-
@printer_klasses = @options[:printers] || {::RubyProf::FlatPrinter => 'flat.txt',
|
17
|
-
::RubyProf::GraphPrinter => 'graph.txt',
|
18
|
-
::RubyProf::GraphHtmlPrinter => 'graph.html',
|
19
|
-
::RubyProf::CallStackPrinter => 'call_stack.html'}
|
20
|
-
|
21
16
|
@skip_paths = options[:skip_paths] || [%r{^/assets}, %r{\.css$}, %r{\.js}, %r{\.png}, %r{\.jpeg}]
|
22
17
|
end
|
23
18
|
|
@@ -5,7 +5,7 @@ require File.expand_path('../test_helper', __FILE__)
|
|
5
5
|
|
6
6
|
class MeasureProcessTimeTest < Test::Unit::TestCase
|
7
7
|
def setup
|
8
|
-
# Need to
|
8
|
+
# Need to fix this for linux (windows works since PROCESS_TIME is WALL_TIME anyway)
|
9
9
|
RubyProf::measure_mode = RubyProf::PROCESS_TIME
|
10
10
|
end
|
11
11
|
|
@@ -202,4 +202,4 @@ class MeasureProcessTimeTest < Test::Unit::TestCase
|
|
202
202
|
assert_in_delta(0.0, methods[1].wait_time, 0.01)
|
203
203
|
assert_in_delta(0.0, methods[1].self_time, 0.01)
|
204
204
|
end
|
205
|
-
end
|
205
|
+
end
|
data/test/pause_test.rb
CHANGED
@@ -40,18 +40,18 @@ class PauseTest < Test::Unit::TestCase
|
|
40
40
|
assert_equal('Kernel#sleep', methods[2].full_name)
|
41
41
|
|
42
42
|
# Check times
|
43
|
-
assert_in_delta(0.
|
43
|
+
assert_in_delta(0.3, methods[0].total_time, 0.01)
|
44
44
|
assert_in_delta(0, methods[0].wait_time, 0.01)
|
45
45
|
assert_in_delta(0, methods[0].self_time, 0.01)
|
46
46
|
|
47
|
-
assert_in_delta(0.
|
47
|
+
assert_in_delta(0.3, methods[1].total_time, 0.01)
|
48
48
|
assert_in_delta(0, methods[1].wait_time, 0.01)
|
49
49
|
assert_in_delta(0, methods[1].self_time, 0.01)
|
50
50
|
|
51
|
-
assert_in_delta(0.
|
51
|
+
assert_in_delta(0.3, methods[2].total_time, 0.01)
|
52
52
|
assert_in_delta(0, methods[2].wait_time, 0.01)
|
53
|
-
assert_in_delta(0.
|
53
|
+
assert_in_delta(0.3, methods[2].self_time, 0.01)
|
54
54
|
|
55
55
|
end
|
56
56
|
|
57
|
-
end
|
57
|
+
end
|
data/test/prime.rb
CHANGED
data/test/printers_test.rb
CHANGED
@@ -259,6 +259,8 @@ class PrintersTest < Test::Unit::TestCase
|
|
259
259
|
end
|
260
260
|
|
261
261
|
def assert_sorted array
|
262
|
+
array = array.map{|n| n.to_f} # allow for > 10s times to sort right, since lexographically 4.0 > 10.0
|
262
263
|
assert_equal array, array.sort.reverse, "Array #{array.inspect} is not sorted"
|
263
264
|
end
|
265
|
+
|
264
266
|
end
|
data/test/recursive_test.rb
CHANGED
@@ -214,7 +214,7 @@ class RecursiveTest < Test::Unit::TestCase
|
|
214
214
|
assert_in_delta(5, method.total_time, 0.1)
|
215
215
|
assert_in_delta(0, method.self_time, 0.1)
|
216
216
|
assert_in_delta(0, method.wait_time, 0.01)
|
217
|
-
assert_in_delta(5, method.children_time, 0.
|
217
|
+
assert_in_delta(5, method.children_time, 0.05)
|
218
218
|
|
219
219
|
assert_equal(3, method.call_infos.length)
|
220
220
|
call_info = method.call_infos[0]
|
@@ -256,4 +256,4 @@ class RecursiveTest < Test::Unit::TestCase
|
|
256
256
|
assert_equal(0, call_info.children.length)
|
257
257
|
assert(!call_info.recursive)
|
258
258
|
end
|
259
|
-
end
|
259
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-prof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|
@@ -89,7 +89,6 @@ files:
|
|
89
89
|
- ext/ruby_prof/version.h
|
90
90
|
- ext/ruby_prof/vc/ruby_prof.sln
|
91
91
|
- ext/ruby_prof/vc/ruby_prof.vcxproj
|
92
|
-
- ext/ruby_prof/vc/ruby_prof_18.vcxproj
|
93
92
|
- lib/ruby-prof.rb
|
94
93
|
- lib/unprof.rb
|
95
94
|
- lib/ruby-prof/aggregate_call_info.rb
|
@@ -116,7 +115,6 @@ files:
|
|
116
115
|
- lib/ruby-prof/printers/multi_printer.rb
|
117
116
|
- test/aggregate_test.rb
|
118
117
|
- test/basic_test.rb
|
119
|
-
- test/bug_test.rb
|
120
118
|
- test/call_info_visitor_test.rb
|
121
119
|
- test/duplicate_names_test.rb
|
122
120
|
- test/dynamic_method_test.rb
|
@@ -124,7 +122,6 @@ files:
|
|
124
122
|
- test/exceptions_test.rb
|
125
123
|
- test/exclude_threads_test.rb
|
126
124
|
- test/exec_test.rb
|
127
|
-
- test/gc_test.rb
|
128
125
|
- test/line_number_test.rb
|
129
126
|
- test/measure_allocations_test.rb
|
130
127
|
- test/measure_cpu_time_test.rb
|
@@ -1,108 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
2
|
-
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
3
|
-
<ItemGroup Label="ProjectConfigurations">
|
4
|
-
<ProjectConfiguration Include="Debug|Win32">
|
5
|
-
<Configuration>Debug</Configuration>
|
6
|
-
<Platform>Win32</Platform>
|
7
|
-
</ProjectConfiguration>
|
8
|
-
<ProjectConfiguration Include="Release|Win32">
|
9
|
-
<Configuration>Release</Configuration>
|
10
|
-
<Platform>Win32</Platform>
|
11
|
-
</ProjectConfiguration>
|
12
|
-
</ItemGroup>
|
13
|
-
<ItemGroup>
|
14
|
-
<ClInclude Include="..\rp_call_info.h" />
|
15
|
-
<ClInclude Include="..\rp_measure.h" />
|
16
|
-
<ClInclude Include="..\rp_method.h" />
|
17
|
-
<ClInclude Include="..\rp_stack.h" />
|
18
|
-
<ClInclude Include="..\rp_thread.h" />
|
19
|
-
<ClInclude Include="..\ruby_prof.h" />
|
20
|
-
<ClInclude Include="..\version.h" />
|
21
|
-
</ItemGroup>
|
22
|
-
<ItemGroup>
|
23
|
-
<ClCompile Include="..\rp_call_info.c" />
|
24
|
-
<ClCompile Include="..\rp_measure.c" />
|
25
|
-
<ClCompile Include="..\rp_measure_allocations.c" />
|
26
|
-
<ClCompile Include="..\rp_measure_cpu_time.c" />
|
27
|
-
<ClCompile Include="..\rp_measure_gc_runs.c" />
|
28
|
-
<ClCompile Include="..\rp_measure_gc_time.c" />
|
29
|
-
<ClCompile Include="..\rp_measure_memory.c" />
|
30
|
-
<ClCompile Include="..\rp_measure_process_time.c" />
|
31
|
-
<ClCompile Include="..\rp_measure_wall_time.c" />
|
32
|
-
<ClCompile Include="..\rp_method.c" />
|
33
|
-
<ClCompile Include="..\rp_stack.c" />
|
34
|
-
<ClCompile Include="..\rp_thread.c" />
|
35
|
-
<ClCompile Include="..\ruby_prof.c" />
|
36
|
-
</ItemGroup>
|
37
|
-
<PropertyGroup Label="Globals">
|
38
|
-
<ProjectGuid>{7789FC23-D053-4733-9ED1-D6CE099E1237}</ProjectGuid>
|
39
|
-
<Keyword>Win32Proj</Keyword>
|
40
|
-
<RootNamespace>ruby_prof_18</RootNamespace>
|
41
|
-
</PropertyGroup>
|
42
|
-
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
43
|
-
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
44
|
-
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
45
|
-
<UseDebugLibraries>true</UseDebugLibraries>
|
46
|
-
<CharacterSet>Unicode</CharacterSet>
|
47
|
-
</PropertyGroup>
|
48
|
-
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
49
|
-
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
50
|
-
<UseDebugLibraries>false</UseDebugLibraries>
|
51
|
-
<WholeProgramOptimization>true</WholeProgramOptimization>
|
52
|
-
<CharacterSet>Unicode</CharacterSet>
|
53
|
-
</PropertyGroup>
|
54
|
-
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
55
|
-
<ImportGroup Label="ExtensionSettings">
|
56
|
-
</ImportGroup>
|
57
|
-
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
58
|
-
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
59
|
-
</ImportGroup>
|
60
|
-
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
61
|
-
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
62
|
-
</ImportGroup>
|
63
|
-
<PropertyGroup Label="UserMacros" />
|
64
|
-
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
65
|
-
<LinkIncremental>true</LinkIncremental>
|
66
|
-
<OutDir>C:\MinGW\local\src\ruby-prof\lib\1.8</OutDir>
|
67
|
-
<TargetExt>.so</TargetExt>
|
68
|
-
<TargetName>ruby_prof</TargetName>
|
69
|
-
</PropertyGroup>
|
70
|
-
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
71
|
-
<LinkIncremental>false</LinkIncremental>
|
72
|
-
</PropertyGroup>
|
73
|
-
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
74
|
-
<ClCompile>
|
75
|
-
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
76
|
-
<WarningLevel>Level3</WarningLevel>
|
77
|
-
<Optimization>Disabled</Optimization>
|
78
|
-
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;RUBY_PROF_18_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
79
|
-
<AdditionalIncludeDirectories>C:\MinGW\local\ruby187vc\lib\ruby\1.8\i386-mswin32_100</AdditionalIncludeDirectories>
|
80
|
-
</ClCompile>
|
81
|
-
<Link>
|
82
|
-
<SubSystem>Windows</SubSystem>
|
83
|
-
<GenerateDebugInformation>true</GenerateDebugInformation>
|
84
|
-
<AdditionalLibraryDirectories>C:\MinGW\local\ruby187vc\lib</AdditionalLibraryDirectories>
|
85
|
-
<AdditionalDependencies>msvcr100-ruby18.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
86
|
-
<ModuleDefinitionFile>ruby_prof.def</ModuleDefinitionFile>
|
87
|
-
</Link>
|
88
|
-
</ItemDefinitionGroup>
|
89
|
-
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
90
|
-
<ClCompile>
|
91
|
-
<WarningLevel>Level3</WarningLevel>
|
92
|
-
<PrecompiledHeader>Use</PrecompiledHeader>
|
93
|
-
<Optimization>MaxSpeed</Optimization>
|
94
|
-
<FunctionLevelLinking>true</FunctionLevelLinking>
|
95
|
-
<IntrinsicFunctions>true</IntrinsicFunctions>
|
96
|
-
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;RUBY_PROF_18_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
97
|
-
</ClCompile>
|
98
|
-
<Link>
|
99
|
-
<SubSystem>Windows</SubSystem>
|
100
|
-
<GenerateDebugInformation>true</GenerateDebugInformation>
|
101
|
-
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
102
|
-
<OptimizeReferences>true</OptimizeReferences>
|
103
|
-
</Link>
|
104
|
-
</ItemDefinitionGroup>
|
105
|
-
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
106
|
-
<ImportGroup Label="ExtensionTargets">
|
107
|
-
</ImportGroup>
|
108
|
-
</Project>
|
data/test/bug_test.rb
DELETED
data/test/gc_test.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
require File.expand_path('../test_helper', __FILE__)
|
5
|
-
|
6
|
-
class GcTest < Test::Unit::TestCase
|
7
|
-
def setup
|
8
|
-
# Need to use wall time for this test due to the sleep calls
|
9
|
-
RubyProf::measure_mode = RubyProf::WALL_TIME
|
10
|
-
end
|
11
|
-
|
12
|
-
def run_profile
|
13
|
-
RubyProf.profile do
|
14
|
-
RubyProf::C1.hello
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_gc
|
19
|
-
result = run_profile
|
20
|
-
|
21
|
-
thread = result.threads.first
|
22
|
-
method = thread.methods.first
|
23
|
-
call_info = method.call_infos.first
|
24
|
-
|
25
|
-
result = nil
|
26
|
-
|
27
|
-
1000.times do
|
28
|
-
GC.start
|
29
|
-
Array.new(1000)
|
30
|
-
end
|
31
|
-
|
32
|
-
puts thread.methods
|
33
|
-
puts method.full_name
|
34
|
-
end
|
35
|
-
end
|