ruby-prof 0.11.2 → 0.11.3
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/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
|