ruby-prof 1.1.0 → 1.2.0
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.
- checksums.yaml +4 -4
- data/CHANGES +12 -1
- data/bin/ruby-prof +100 -152
- data/ext/ruby_prof/rp_aggregate_call_tree.c +41 -0
- data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
- data/ext/ruby_prof/rp_allocation.c +31 -51
- data/ext/ruby_prof/rp_allocation.h +2 -2
- data/ext/ruby_prof/rp_call_tree.c +353 -0
- data/ext/ruby_prof/rp_call_tree.h +43 -0
- data/ext/ruby_prof/rp_call_trees.c +266 -0
- data/ext/ruby_prof/rp_call_trees.h +29 -0
- data/ext/ruby_prof/rp_measure_allocations.c +11 -13
- data/ext/ruby_prof/rp_measure_process_time.c +11 -13
- data/ext/ruby_prof/rp_measure_wall_time.c +17 -15
- data/ext/ruby_prof/rp_measurement.c +27 -36
- data/ext/ruby_prof/rp_measurement.h +6 -6
- data/ext/ruby_prof/rp_method.c +88 -248
- data/ext/ruby_prof/rp_method.h +12 -19
- data/ext/ruby_prof/rp_profile.c +277 -270
- data/ext/ruby_prof/rp_profile.h +0 -1
- data/ext/ruby_prof/rp_stack.c +113 -105
- data/ext/ruby_prof/rp_stack.h +15 -18
- data/ext/ruby_prof/rp_thread.c +115 -107
- data/ext/ruby_prof/rp_thread.h +9 -8
- data/ext/ruby_prof/ruby_prof.c +27 -23
- data/ext/ruby_prof/ruby_prof.h +9 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -7
- data/lib/ruby-prof.rb +2 -3
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +4 -7
- data/lib/ruby-prof/assets/graph_printer.html.erb +5 -6
- data/lib/ruby-prof/{call_info.rb → call_tree.rb} +6 -6
- data/lib/ruby-prof/call_tree_visitor.rb +36 -0
- data/lib/ruby-prof/measurement.rb +5 -2
- data/lib/ruby-prof/method_info.rb +3 -15
- data/lib/ruby-prof/printers/call_info_printer.rb +12 -10
- data/lib/ruby-prof/printers/call_stack_printer.rb +19 -22
- data/lib/ruby-prof/printers/call_tree_printer.rb +1 -1
- data/lib/ruby-prof/printers/dot_printer.rb +3 -3
- data/lib/ruby-prof/printers/graph_printer.rb +3 -4
- data/lib/ruby-prof/printers/multi_printer.rb +2 -2
- data/lib/ruby-prof/rack.rb +3 -0
- data/lib/ruby-prof/thread.rb +3 -18
- data/lib/ruby-prof/version.rb +1 -1
- data/ruby-prof.gemspec +7 -0
- data/test/alias_test.rb +42 -45
- data/test/basic_test.rb +0 -86
- data/test/{call_info_visitor_test.rb → call_tree_visitor_test.rb} +6 -5
- data/test/call_trees_test.rb +66 -0
- data/test/exclude_methods_test.rb +17 -12
- data/test/fiber_test.rb +203 -6
- data/test/gc_test.rb +32 -23
- data/test/inverse_call_tree_test.rb +175 -0
- data/test/line_number_test.rb +64 -67
- data/test/marshal_test.rb +7 -11
- data/test/measure_allocations_test.rb +224 -234
- data/test/measure_allocations_trace_test.rb +224 -234
- data/test/measure_memory_trace_test.rb +814 -469
- data/test/measure_process_time_test.rb +0 -64
- data/test/measure_times.rb +2 -0
- data/test/measure_wall_time_test.rb +34 -58
- data/test/pause_resume_test.rb +19 -10
- data/test/prime.rb +1 -3
- data/test/prime_script.rb +6 -0
- data/test/printers_test.rb +1 -1
- data/test/recursive_test.rb +50 -54
- data/test/start_stop_test.rb +19 -19
- data/test/test_helper.rb +3 -15
- data/test/thread_test.rb +11 -11
- data/test/unique_call_path_test.rb +25 -95
- metadata +19 -9
- data/ext/ruby_prof/rp_call_info.c +0 -271
- data/ext/ruby_prof/rp_call_info.h +0 -35
- data/lib/ruby-prof/call_info_visitor.rb +0 -38
- data/test/parser_timings.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0006623bb548f82d74fa8bdd6cfa8e257ec5deea1d4f37f53dab8d9c780427d9
|
4
|
+
data.tar.gz: b30fd0deaf1ac3c3acf8519e3280aac4fc2b48a402658905ffe2f68c14edb80a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7869ef3006a8e36883b5fb6f592eacf7d0243ef1959c0f1b8f67f378004bb880199ffa0914d5df4807ae35cd0c7843de1f2379a0602c798f83b4b0e25b6d764d
|
7
|
+
data.tar.gz: d804cfc1f3c77f864583b5afcbf608bce6d9af098343a9212cb1a7e19488f2fae7177d225a55887249c85ee15efc2d6b1c239b5b847b9fd7deca298aa3a368a6
|
data/CHANGES
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
1.2.0 (2020-01-23)
|
2
|
+
=====================
|
3
|
+
* Fix call stack printer broken in version 1.0.0 (Charlie Savage)
|
4
|
+
* Ruby 2.7.0 support (Charlie Savage)
|
5
|
+
* Switch to Windows high precision timer for measuring wall time (Charlie Savage)
|
6
|
+
* Much better support for reverse call trees - if you start RubyProf at the bottom
|
7
|
+
of a call tree it will correctly calculate times as it ascends the tree (Charlie Savage)
|
8
|
+
* Port AggregateCallInfo from Ruby to C to increase performance
|
9
|
+
* API change - CallInfo has been renamed CallTree
|
10
|
+
* Fix crashes on Ruby 2.4.*
|
11
|
+
|
1
12
|
1.1.0 (2019-12-14)
|
2
13
|
=====================
|
3
14
|
Changes
|
@@ -342,7 +353,7 @@ Fixes
|
|
342
353
|
|
343
354
|
0.7.1 (2008-11-28)
|
344
355
|
========================
|
345
|
-
* Added new
|
356
|
+
* Added new AggregateCallTree class for printers to
|
346
357
|
make results easier to read. Take this call sequence
|
347
358
|
for example:
|
348
359
|
|
data/bin/ruby-prof
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
|
3
3
|
# First require ruby-prof
|
4
|
-
require 'rubygems'
|
5
4
|
require 'ruby-prof'
|
6
5
|
|
7
6
|
# Now setup option parser
|
@@ -14,64 +13,45 @@ module RubyProf
|
|
14
13
|
# Profiles a Ruby program.
|
15
14
|
#
|
16
15
|
# == Usage
|
17
|
-
#
|
18
|
-
# ruby_prof [options] <script.rb> [--] [script-options]
|
16
|
+
# ruby-prof [options] <script.rb> [--] [profiled-script-command-line-options]
|
19
17
|
#
|
20
18
|
# Options:
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
|
53
|
-
# -d Set $DEBUG to true
|
54
|
-
#
|
55
|
-
# -R, --require-noprof lib Require a specific library (not profiled)
|
56
|
-
#
|
57
|
-
# -E, --eval-noprof code Execute the ruby statements (not profiled)
|
58
|
-
#
|
59
|
-
# -x, --exclude regexp Exclude methods by regexp (see method elimination)
|
60
|
-
#
|
61
|
-
# -X, --exclude-file file Exclude methods by regexp listed in file (see method elimination)
|
62
|
-
#
|
63
|
-
# --exclude-common-cycles Make common iterators like Integer#times appear inlined
|
64
|
-
#
|
65
|
-
# --exclude-common-callbacks Make common callbacks invocations like Integer#times appear inlined so you can see call origins in graph
|
66
|
-
#
|
67
|
-
# -h, --help Show help message
|
68
|
-
#
|
69
|
-
# --version Show version
|
70
|
-
#
|
71
|
-
#
|
19
|
+
# -p, --printer=printer Select a printer:
|
20
|
+
# flat - Prints a flat profile as text (default).
|
21
|
+
# graph - Prints a graph profile as text.
|
22
|
+
# graph_html - Prints a graph profile as html.
|
23
|
+
# call_tree - format for KCacheGrind
|
24
|
+
# call_stack - prints a HTML visualization of the call tree
|
25
|
+
# dot - Prints a graph profile as a dot file
|
26
|
+
# multi - Creates several reports in output directory
|
27
|
+
# -m, --min_percent=min_percent The minimum percent a method must take before
|
28
|
+
# being included in output reports.
|
29
|
+
# This option is not supported for call tree.
|
30
|
+
# -f, --file=path Output results to a file instead of standard out.
|
31
|
+
# --mode=measure_mode Select what ruby-prof should measure:
|
32
|
+
# wall - Wall time (default).
|
33
|
+
# process - Process time.
|
34
|
+
# allocations - Object allocations (requires patched Ruby interpreter).
|
35
|
+
# memory - Allocated memory in KB (requires patched Ruby interpreter).
|
36
|
+
# -s, --sort=sort_mode Select how ruby-prof results should be sorted:
|
37
|
+
# total - Total time
|
38
|
+
# self - Self time
|
39
|
+
# wait - Wait time
|
40
|
+
# child - Child time
|
41
|
+
# --allow_exceptions Raise exceptions encountered during profiling (true) or suppress them (false)
|
42
|
+
# -R, --require-noprof=lib require a specific library (not profiled)
|
43
|
+
# -E, --eval-noprof=code execute the ruby statements (not profiled)
|
44
|
+
# --exclude=methods A comma separated list of methods to exclude.
|
45
|
+
# Specify instance methods via # (Integer#times)
|
46
|
+
# Specify class methods via . (Integer.superclass)
|
47
|
+
# --exclude-common Remove common methods from the profile
|
48
|
+
# -h, --help Show help message
|
49
|
+
# -v, --version version Show version (1.1.0)
|
50
|
+
|
72
51
|
class Cmd
|
73
52
|
# :enddoc:
|
74
53
|
attr_accessor :options
|
54
|
+
attr_reader :profile
|
75
55
|
|
76
56
|
def initialize
|
77
57
|
setup_options
|
@@ -84,15 +64,52 @@ module RubyProf
|
|
84
64
|
def setup_options
|
85
65
|
@options = OpenStruct.new
|
86
66
|
options.printer = RubyProf::FlatPrinter
|
67
|
+
options.measure_mode = RubyProf::WALL_TIME
|
87
68
|
options.min_percent = 0
|
88
69
|
options.file = nil
|
89
|
-
options.
|
90
|
-
options.
|
91
|
-
|
70
|
+
options.allow_exceptions = false
|
71
|
+
options.exclude_common = false
|
72
|
+
options.exclude = Array.new
|
92
73
|
options.pre_libs = Array.new
|
93
74
|
options.pre_execs = Array.new
|
94
75
|
end
|
95
76
|
|
77
|
+
# This is copied from ActiveSupport:
|
78
|
+
def constantize(camel_cased_word)
|
79
|
+
if !camel_cased_word.include?("::")
|
80
|
+
Object.const_get(camel_cased_word)
|
81
|
+
else
|
82
|
+
names = camel_cased_word.split("::")
|
83
|
+
|
84
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
85
|
+
Object.const_get(camel_cased_word) if names.empty?
|
86
|
+
|
87
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
88
|
+
names.shift if names.size > 1 && names.first.empty?
|
89
|
+
|
90
|
+
names.inject(Object) do |constant, name|
|
91
|
+
if constant == Object
|
92
|
+
constant.const_get(name)
|
93
|
+
else
|
94
|
+
candidate = constant.const_get(name)
|
95
|
+
next candidate if constant.const_defined?(name, false)
|
96
|
+
next candidate unless Object.const_defined?(name)
|
97
|
+
|
98
|
+
# Go down the ancestors to check if it is owned directly. The check
|
99
|
+
# stops when we reach Object or the end of ancestors tree.
|
100
|
+
constant = constant.ancestors.inject(constant) do |const, ancestor|
|
101
|
+
break const if ancestor == Object
|
102
|
+
break ancestor if ancestor.const_defined?(name, false)
|
103
|
+
const
|
104
|
+
end
|
105
|
+
|
106
|
+
# owner is in Object, so raise
|
107
|
+
constant.const_get(name, false)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
96
113
|
def option_parser
|
97
114
|
OptionParser.new do |opts|
|
98
115
|
opts.banner = "ruby_prof #{RubyProf::VERSION}\n" +
|
@@ -182,94 +199,45 @@ module RubyProf
|
|
182
199
|
end
|
183
200
|
end
|
184
201
|
|
185
|
-
opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
|
186
|
-
options.replace_prog_name = true
|
187
|
-
end
|
188
|
-
|
189
|
-
if defined?(RubyVM)
|
190
|
-
opts.on("--specialized-instruction", "Turn on specified instruction.") do
|
191
|
-
options.specialized_instruction = true
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
202
|
opts.on_tail("-h", "--help", "Show help message") do
|
196
203
|
puts opts
|
197
204
|
exit
|
198
205
|
end
|
199
206
|
|
200
|
-
opts.on_tail("--version", "Show version #{RubyProf::VERSION}") do
|
207
|
+
opts.on_tail("-v version", "--version", "Show version (#{RubyProf::VERSION})") do
|
201
208
|
puts "ruby_prof " + RubyProf::VERSION
|
202
209
|
exit
|
203
210
|
end
|
204
211
|
|
205
|
-
opts.on(
|
206
|
-
|
207
|
-
$VERBOSE = true
|
208
|
-
end
|
209
|
-
|
210
|
-
opts.on("-d", "Set $DEBUG to true") do
|
211
|
-
$DEBUG = true
|
212
|
+
opts.on('--allow_exceptions', 'Raise exceptions encountered during profiling (true) or suppress them (false)') do
|
213
|
+
options.allow_exceptions = true
|
212
214
|
end
|
213
215
|
|
214
|
-
opts.on('-R lib', '--require-noprof
|
216
|
+
opts.on('-R lib', '--require-noprof=lib', 'require a specific library (not profiled)') do |lib|
|
215
217
|
options.pre_libs << lib
|
216
218
|
end
|
217
219
|
|
218
|
-
opts.on('-E code', '--eval-noprof
|
220
|
+
opts.on('-E code', '--eval-noprof=code', 'execute the ruby statements (not profiled)') do |code|
|
219
221
|
options.pre_execs << code
|
220
222
|
end
|
221
223
|
|
222
|
-
opts.on('
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
Integer#times
|
236
|
-
Integer#upto
|
237
|
-
Integer#downto
|
238
|
-
Enumerator#each
|
239
|
-
Enumerator#each_with_index
|
240
|
-
Enumerator#each_with_object
|
241
|
-
|
242
|
-
Array#each
|
243
|
-
Array#each_index
|
244
|
-
Array#reverse_each
|
245
|
-
Array#map
|
246
|
-
|
247
|
-
Hash#each
|
248
|
-
Hash#each_pair
|
249
|
-
Hash#each_key
|
250
|
-
Hash#each_value
|
251
|
-
|
252
|
-
Range#each
|
253
|
-
Enumerable#each_cons
|
254
|
-
Enumerable#each_entry
|
255
|
-
Enumerable#each_slice
|
256
|
-
Enumerable#each_with_index
|
257
|
-
Enumerable#each_with_object
|
258
|
-
Enumerable#reverse_each
|
259
|
-
Enumerable#inject
|
260
|
-
Enumerable#collect
|
261
|
-
Enumerable#reduce
|
262
|
-
}
|
263
|
-
#TODO: may be the whole Enumerable module should be excluded via 'Enumerable#.*', we need feedback on use cases.
|
224
|
+
opts.on('--exclude=methods', String,
|
225
|
+
'A comma separated list of methods to exclude.',
|
226
|
+
' Specify instance methods via # (Integer#times)',
|
227
|
+
' Specify class methods via . (Integer.superclass)') do |exclude_string|
|
228
|
+
exclude_string.split(',').each do |string|
|
229
|
+
match = string.strip.match(/(.*)(#|\.)(.*)/)
|
230
|
+
klass = constantize(match[1])
|
231
|
+
if match[2] == '.'
|
232
|
+
klass = klass.singleton_class
|
233
|
+
end
|
234
|
+
method = match[3].to_sym
|
235
|
+
options.exclude << [klass, method]
|
236
|
+
end
|
264
237
|
end
|
265
238
|
|
266
|
-
opts.on('--exclude-common
|
267
|
-
options.
|
268
|
-
options.eliminate_methods += %w{
|
269
|
-
Method#call
|
270
|
-
Proc#call
|
271
|
-
ActiveSupport::Callbacks::ClassMethods#__run_callback
|
272
|
-
}
|
239
|
+
opts.on('--exclude-common', 'Remove common methods from the profile') do
|
240
|
+
options.exclude_common = true
|
273
241
|
end
|
274
242
|
end
|
275
243
|
end
|
@@ -313,23 +281,15 @@ module RubyProf
|
|
313
281
|
end
|
314
282
|
|
315
283
|
def run
|
316
|
-
# Get the script we will execute
|
317
284
|
script = ARGV.shift
|
318
|
-
|
319
|
-
|
285
|
+
@profile = Profile.new(options.to_h)
|
286
|
+
options.exclude.each do |klass, method|
|
287
|
+
@profile.exclude_method!(klass, method)
|
320
288
|
end
|
321
289
|
|
322
|
-
|
323
|
-
|
324
|
-
RubyVM::InstructionSequence.compile_option = {
|
325
|
-
:trace_instruction => true,
|
326
|
-
:specialized_instruction => options.specialized_instruction
|
327
|
-
}
|
290
|
+
profile.profile do
|
291
|
+
load script
|
328
292
|
end
|
329
|
-
|
330
|
-
# Set the measure mode
|
331
|
-
RubyProf.measure_mode = options.measure_mode if options.measure_mode
|
332
|
-
RubyProf.start_script(script)
|
333
293
|
end
|
334
294
|
end
|
335
295
|
end
|
@@ -342,20 +302,8 @@ cmd = RubyProf::Cmd.new
|
|
342
302
|
# *after* any other one that will be installed.
|
343
303
|
|
344
304
|
at_exit {
|
345
|
-
# Stop profiling
|
346
|
-
result = RubyProf.stop
|
347
|
-
|
348
|
-
# Eliminate unwanted methods from call graph
|
349
|
-
if cmd.options.eliminate_methods
|
350
|
-
result.eliminate_methods!(cmd.options.eliminate_methods)
|
351
|
-
end
|
352
|
-
|
353
|
-
if cmd.options.eliminate_methods_files
|
354
|
-
cmd.options.eliminate_methods_files.each {|f| result.eliminate_methods!(f)}
|
355
|
-
end
|
356
|
-
|
357
305
|
# Create a printer
|
358
|
-
printer = cmd.options.printer.new(
|
306
|
+
printer = cmd.options.printer.new(cmd.profile)
|
359
307
|
printer_options = {:min_percent => cmd.options.min_percent, :sort_method => cmd.options.sort_method}
|
360
308
|
|
361
309
|
# Get output
|
@@ -0,0 +1,41 @@
|
|
1
|
+
/* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
|
+
Please see the LICENSE file for copyright and distribution information */
|
3
|
+
|
4
|
+
#include "rp_aggregate_call_tree.h"
|
5
|
+
|
6
|
+
VALUE cRpAggregateCallTree;
|
7
|
+
|
8
|
+
void prof_aggregate_call_tree_mark(void* data)
|
9
|
+
{
|
10
|
+
prof_call_tree_t* call_tree = (prof_call_tree_t*)data;
|
11
|
+
|
12
|
+
if (call_tree->object != Qnil)
|
13
|
+
rb_gc_mark(call_tree->object);
|
14
|
+
|
15
|
+
if (call_tree->source_file != Qnil)
|
16
|
+
rb_gc_mark(call_tree->source_file);
|
17
|
+
|
18
|
+
prof_measurement_mark(call_tree->measurement);
|
19
|
+
}
|
20
|
+
|
21
|
+
static void prof_aggregate_call_tree_ruby_gc_free(void* data)
|
22
|
+
{
|
23
|
+
prof_call_tree_t* call_tree = (prof_call_tree_t*)data;
|
24
|
+
prof_call_tree_free(call_tree);
|
25
|
+
}
|
26
|
+
|
27
|
+
VALUE prof_aggregate_call_tree_wrap(prof_call_tree_t* call_tree)
|
28
|
+
{
|
29
|
+
if (call_tree->object == Qnil)
|
30
|
+
{
|
31
|
+
call_tree->object = Data_Wrap_Struct(cRpAggregateCallTree, prof_aggregate_call_tree_mark, prof_aggregate_call_tree_ruby_gc_free, call_tree);
|
32
|
+
}
|
33
|
+
return call_tree->object;
|
34
|
+
}
|
35
|
+
|
36
|
+
void rp_init_aggregate_call_tree()
|
37
|
+
{
|
38
|
+
// AggregateCallTree
|
39
|
+
cRpAggregateCallTree = rb_define_class_under(mProf, "AggregateCallTree", cRpCallTree);
|
40
|
+
rb_undef_method(CLASS_OF(cRpAggregateCallTree), "new");
|
41
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
|
+
Please see the LICENSE file for copyright and distribution information */
|
3
|
+
|
4
|
+
#ifndef __RP_AGGREGATE_CALL_TREE_H__
|
5
|
+
#define __RP_AGGREGATE_CALL_TREE_H__
|
6
|
+
|
7
|
+
#include "ruby_prof.h"
|
8
|
+
#include "rp_call_tree.h"
|
9
|
+
|
10
|
+
void rp_init_aggregate_call_tree(void);
|
11
|
+
VALUE prof_aggregate_call_tree_wrap(prof_call_tree_t* call_tree);
|
12
|
+
|
13
|
+
#endif //__RP_AGGREGATE_CALL_TREE_H__
|
@@ -5,12 +5,11 @@
|
|
5
5
|
|
6
6
|
VALUE cRpAllocation;
|
7
7
|
|
8
|
-
prof_allocation_t*
|
9
|
-
allocations_table_lookup(st_table *table, st_data_t key)
|
8
|
+
prof_allocation_t* allocations_table_lookup(st_table* table, st_data_t key)
|
10
9
|
{
|
11
10
|
prof_allocation_t* result = NULL;
|
12
11
|
st_data_t value;
|
13
|
-
if (
|
12
|
+
if (rb_st_lookup(table, key, &value))
|
14
13
|
{
|
15
14
|
result = (prof_allocation_t*)value;
|
16
15
|
}
|
@@ -18,23 +17,20 @@ allocations_table_lookup(st_table *table, st_data_t key)
|
|
18
17
|
return result;
|
19
18
|
}
|
20
19
|
|
21
|
-
void
|
22
|
-
allocations_table_insert(st_table *table, st_data_t key, prof_allocation_t * allocation)
|
20
|
+
void allocations_table_insert(st_table* table, st_data_t key, prof_allocation_t* allocation)
|
23
21
|
{
|
24
|
-
|
22
|
+
rb_st_insert(table, (st_data_t)key, (st_data_t)allocation);
|
25
23
|
}
|
26
24
|
|
27
|
-
st_data_t
|
28
|
-
allocations_key(VALUE klass, int source_line)
|
25
|
+
st_data_t allocations_key(VALUE klass, int source_line)
|
29
26
|
{
|
30
27
|
return (klass << 4) + source_line;
|
31
28
|
}
|
32
29
|
|
33
30
|
/* ====== prof_allocation_t ====== */
|
34
|
-
prof_allocation_t*
|
35
|
-
prof_allocation_create(void)
|
31
|
+
prof_allocation_t* prof_allocation_create(void)
|
36
32
|
{
|
37
|
-
prof_allocation_t
|
33
|
+
prof_allocation_t* result = ALLOC(prof_allocation_t);
|
38
34
|
result->count = 0;
|
39
35
|
result->klass = Qnil;
|
40
36
|
result->klass_name = Qnil;
|
@@ -47,8 +43,7 @@ prof_allocation_create(void)
|
|
47
43
|
return result;
|
48
44
|
}
|
49
45
|
|
50
|
-
prof_allocation_t*
|
51
|
-
prof_allocate_increment(prof_method_t* method, rb_trace_arg_t* trace_arg)
|
46
|
+
prof_allocation_t* prof_allocate_increment(prof_method_t* method, rb_trace_arg_t* trace_arg)
|
52
47
|
{
|
53
48
|
VALUE object = rb_tracearg_object(trace_arg);
|
54
49
|
if (BUILTIN_TYPE(object) == T_IMEMO)
|
@@ -78,11 +73,14 @@ prof_allocate_increment(prof_method_t* method, rb_trace_arg_t* trace_arg)
|
|
78
73
|
return allocation;
|
79
74
|
}
|
80
75
|
|
81
|
-
static void
|
82
|
-
prof_allocation_ruby_gc_free(void *data)
|
76
|
+
static void prof_allocation_ruby_gc_free(void* data)
|
83
77
|
{
|
84
78
|
prof_allocation_t* allocation = (prof_allocation_t*)data;
|
79
|
+
allocation->object = Qnil;
|
80
|
+
}
|
85
81
|
|
82
|
+
void prof_allocation_free(prof_allocation_t* allocation)
|
83
|
+
{
|
86
84
|
/* Has this allocation object been accessed by Ruby? If
|
87
85
|
yes clean it up so to avoid a segmentation fault. */
|
88
86
|
if (allocation->object != Qnil)
|
@@ -92,58 +90,48 @@ prof_allocation_ruby_gc_free(void *data)
|
|
92
90
|
RDATA(allocation->object)->data = NULL;
|
93
91
|
allocation->object = Qnil;
|
94
92
|
}
|
95
|
-
}
|
96
93
|
|
97
|
-
void
|
98
|
-
prof_allocation_free(prof_allocation_t* allocation)
|
99
|
-
{
|
100
|
-
prof_allocation_ruby_gc_free(allocation);
|
101
94
|
xfree(allocation);
|
102
95
|
}
|
103
96
|
|
104
|
-
size_t
|
105
|
-
prof_allocation_size(const void* data)
|
97
|
+
size_t prof_allocation_size(const void* data)
|
106
98
|
{
|
107
99
|
return sizeof(prof_allocation_t);
|
108
100
|
}
|
109
101
|
|
110
|
-
void
|
111
|
-
prof_allocation_mark(void *data)
|
102
|
+
void prof_allocation_mark(void* data)
|
112
103
|
{
|
113
104
|
prof_allocation_t* allocation = (prof_allocation_t*)data;
|
105
|
+
if (allocation->object != Qnil)
|
106
|
+
rb_gc_mark(allocation->object);
|
107
|
+
|
114
108
|
if (allocation->klass != Qnil)
|
115
109
|
rb_gc_mark(allocation->klass);
|
116
|
-
|
110
|
+
|
117
111
|
if (allocation->klass_name != Qnil)
|
118
112
|
rb_gc_mark(allocation->klass_name);
|
119
113
|
|
120
|
-
if (allocation->object != Qnil)
|
121
|
-
rb_gc_mark(allocation->object);
|
122
|
-
|
123
114
|
if (allocation->source_file != Qnil)
|
124
115
|
rb_gc_mark(allocation->source_file);
|
125
116
|
}
|
126
117
|
|
127
|
-
VALUE
|
128
|
-
prof_allocation_wrap(prof_allocation_t *allocation)
|
118
|
+
VALUE prof_allocation_wrap(prof_allocation_t* allocation)
|
129
119
|
{
|
130
120
|
if (allocation->object == Qnil)
|
131
121
|
{
|
132
|
-
allocation->object = Data_Wrap_Struct(cRpAllocation, prof_allocation_mark
|
122
|
+
allocation->object = Data_Wrap_Struct(cRpAllocation, prof_allocation_mark, prof_allocation_ruby_gc_free, allocation);
|
133
123
|
}
|
134
124
|
return allocation->object;
|
135
125
|
}
|
136
126
|
|
137
|
-
static VALUE
|
138
|
-
prof_allocation_allocate(VALUE klass)
|
127
|
+
static VALUE prof_allocation_allocate(VALUE klass)
|
139
128
|
{
|
140
129
|
prof_allocation_t* allocation = prof_allocation_create();
|
141
130
|
allocation->object = prof_allocation_wrap(allocation);
|
142
131
|
return allocation->object;
|
143
132
|
}
|
144
133
|
|
145
|
-
prof_allocation_t*
|
146
|
-
prof_allocation_get(VALUE self)
|
134
|
+
prof_allocation_t* prof_allocation_get(VALUE self)
|
147
135
|
{
|
148
136
|
/* Can't use Data_Get_Struct because that triggers the event hook
|
149
137
|
ending up in endless recursion. */
|
@@ -158,8 +146,7 @@ prof_allocation_get(VALUE self)
|
|
158
146
|
klass -> Class
|
159
147
|
|
160
148
|
Returns the type of Class being allocated. */
|
161
|
-
static VALUE
|
162
|
-
prof_allocation_klass_name(VALUE self)
|
149
|
+
static VALUE prof_allocation_klass_name(VALUE self)
|
163
150
|
{
|
164
151
|
prof_allocation_t* allocation = prof_allocation_get(self);
|
165
152
|
|
@@ -174,8 +161,7 @@ prof_allocation_klass_name(VALUE self)
|
|
174
161
|
|
175
162
|
Returns the klass flags */
|
176
163
|
|
177
|
-
static VALUE
|
178
|
-
prof_allocation_klass_flags(VALUE self)
|
164
|
+
static VALUE prof_allocation_klass_flags(VALUE self)
|
179
165
|
{
|
180
166
|
prof_allocation_t* allocation = prof_allocation_get(self);
|
181
167
|
return INT2FIX(allocation->klass_flags);
|
@@ -185,8 +171,7 @@ prof_allocation_klass_flags(VALUE self)
|
|
185
171
|
source_file -> string
|
186
172
|
|
187
173
|
Returns the the line number where objects were allocated. */
|
188
|
-
static VALUE
|
189
|
-
prof_allocation_source_file(VALUE self)
|
174
|
+
static VALUE prof_allocation_source_file(VALUE self)
|
190
175
|
{
|
191
176
|
prof_allocation_t* allocation = prof_allocation_get(self);
|
192
177
|
return allocation->source_file;
|
@@ -196,8 +181,7 @@ prof_allocation_source_file(VALUE self)
|
|
196
181
|
line -> number
|
197
182
|
|
198
183
|
Returns the the line number where objects were allocated. */
|
199
|
-
static VALUE
|
200
|
-
prof_allocation_source_line(VALUE self)
|
184
|
+
static VALUE prof_allocation_source_line(VALUE self)
|
201
185
|
{
|
202
186
|
prof_allocation_t* allocation = prof_allocation_get(self);
|
203
187
|
return INT2FIX(allocation->source_line);
|
@@ -207,8 +191,7 @@ prof_allocation_source_line(VALUE self)
|
|
207
191
|
count -> number
|
208
192
|
|
209
193
|
Returns the number of times this class has been allocated. */
|
210
|
-
static VALUE
|
211
|
-
prof_allocation_count(VALUE self)
|
194
|
+
static VALUE prof_allocation_count(VALUE self)
|
212
195
|
{
|
213
196
|
prof_allocation_t* allocation = prof_allocation_get(self);
|
214
197
|
return INT2FIX(allocation->count);
|
@@ -218,16 +201,14 @@ prof_allocation_count(VALUE self)
|
|
218
201
|
memory -> number
|
219
202
|
|
220
203
|
Returns the amount of memory allocated. */
|
221
|
-
static VALUE
|
222
|
-
prof_allocation_memory(VALUE self)
|
204
|
+
static VALUE prof_allocation_memory(VALUE self)
|
223
205
|
{
|
224
206
|
prof_allocation_t* allocation = prof_allocation_get(self);
|
225
207
|
return ULL2NUM(allocation->memory);
|
226
208
|
}
|
227
209
|
|
228
210
|
/* :nodoc: */
|
229
|
-
static VALUE
|
230
|
-
prof_allocation_dump(VALUE self)
|
211
|
+
static VALUE prof_allocation_dump(VALUE self)
|
231
212
|
{
|
232
213
|
prof_allocation_t* allocation = DATA_PTR(self);
|
233
214
|
|
@@ -245,8 +226,7 @@ prof_allocation_dump(VALUE self)
|
|
245
226
|
}
|
246
227
|
|
247
228
|
/* :nodoc: */
|
248
|
-
static VALUE
|
249
|
-
prof_allocation_load(VALUE self, VALUE data)
|
229
|
+
static VALUE prof_allocation_load(VALUE self, VALUE data)
|
250
230
|
{
|
251
231
|
prof_allocation_t* allocation = DATA_PTR(self);
|
252
232
|
allocation->object = self;
|