ruby-prof 0.18.0-x64-mingw32 → 1.1.0-x64-mingw32
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 +32 -0
- data/LICENSE +2 -2
- data/README.rdoc +1 -483
- data/Rakefile +3 -6
- data/bin/ruby-prof +65 -30
- data/ext/ruby_prof/extconf.rb +6 -38
- data/ext/ruby_prof/rp_allocation.c +279 -0
- data/ext/ruby_prof/rp_allocation.h +31 -0
- data/ext/ruby_prof/rp_call_info.c +129 -283
- data/ext/ruby_prof/rp_call_info.h +16 -34
- data/ext/ruby_prof/rp_measure_allocations.c +25 -49
- data/ext/ruby_prof/rp_measure_memory.c +21 -56
- data/ext/ruby_prof/rp_measure_process_time.c +35 -39
- data/ext/ruby_prof/rp_measure_wall_time.c +36 -19
- data/ext/ruby_prof/rp_measurement.c +230 -0
- data/ext/ruby_prof/rp_measurement.h +50 -0
- data/ext/ruby_prof/rp_method.c +389 -389
- data/ext/ruby_prof/rp_method.h +34 -39
- data/ext/ruby_prof/rp_profile.c +895 -0
- data/ext/ruby_prof/rp_profile.h +37 -0
- data/ext/ruby_prof/rp_stack.c +103 -80
- data/ext/ruby_prof/rp_stack.h +5 -12
- data/ext/ruby_prof/rp_thread.c +143 -83
- data/ext/ruby_prof/rp_thread.h +15 -6
- data/ext/ruby_prof/ruby_prof.c +11 -757
- data/ext/ruby_prof/ruby_prof.h +4 -47
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +10 -8
- data/lib/{2.6.3 → 2.6.5}/ruby_prof.so +0 -0
- data/lib/ruby-prof.rb +2 -18
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +713 -0
- data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
- data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
- data/lib/ruby-prof/call_info.rb +35 -93
- data/lib/ruby-prof/call_info_visitor.rb +19 -21
- data/lib/ruby-prof/compatibility.rb +37 -107
- data/lib/ruby-prof/exclude_common_methods.rb +198 -0
- data/lib/ruby-prof/measurement.rb +14 -0
- data/lib/ruby-prof/method_info.rb +52 -83
- data/lib/ruby-prof/printers/abstract_printer.rb +73 -50
- data/lib/ruby-prof/printers/call_info_printer.rb +13 -3
- data/lib/ruby-prof/printers/call_stack_printer.rb +62 -145
- data/lib/ruby-prof/printers/call_tree_printer.rb +20 -12
- data/lib/ruby-prof/printers/dot_printer.rb +5 -5
- data/lib/ruby-prof/printers/flat_printer.rb +6 -24
- data/lib/ruby-prof/printers/graph_html_printer.rb +6 -192
- data/lib/ruby-prof/printers/graph_printer.rb +13 -15
- data/lib/ruby-prof/printers/multi_printer.rb +66 -23
- data/lib/ruby-prof/profile.rb +10 -3
- data/lib/ruby-prof/rack.rb +0 -3
- data/lib/ruby-prof/thread.rb +12 -12
- data/lib/ruby-prof/version.rb +1 -1
- data/ruby-prof.gemspec +2 -2
- data/test/abstract_printer_test.rb +0 -27
- data/test/alias_test.rb +129 -0
- data/test/basic_test.rb +41 -40
- data/test/call_info_visitor_test.rb +3 -3
- data/test/dynamic_method_test.rb +0 -2
- data/test/fiber_test.rb +11 -17
- data/test/gc_test.rb +96 -0
- data/test/line_number_test.rb +120 -39
- data/test/marshal_test.rb +119 -0
- data/test/measure_allocations.rb +30 -0
- data/test/measure_allocations_test.rb +371 -12
- data/test/measure_allocations_trace_test.rb +385 -0
- data/test/measure_memory_trace_test.rb +756 -0
- data/test/measure_process_time_test.rb +821 -33
- data/test/measure_times.rb +54 -0
- data/test/measure_wall_time_test.rb +349 -145
- data/test/multi_printer_test.rb +1 -34
- data/test/parser_timings.rb +24 -0
- data/test/pause_resume_test.rb +5 -5
- data/test/prime.rb +2 -0
- data/test/printer_call_stack_test.rb +28 -0
- data/test/printer_call_tree_test.rb +31 -0
- data/test/printer_flat_test.rb +68 -0
- data/test/printer_graph_html_test.rb +60 -0
- data/test/printer_graph_test.rb +41 -0
- data/test/printers_test.rb +32 -166
- data/test/printing_recursive_graph_test.rb +26 -72
- data/test/recursive_test.rb +72 -77
- data/test/stack_printer_test.rb +2 -15
- data/test/start_stop_test.rb +22 -25
- data/test/test_helper.rb +5 -248
- data/test/thread_test.rb +11 -54
- data/test/unique_call_path_test.rb +16 -28
- data/test/yarv_test.rb +1 -0
- metadata +28 -36
- data/examples/flat.txt +0 -50
- data/examples/graph.dot +0 -84
- data/examples/graph.html +0 -823
- data/examples/graph.txt +0 -139
- data/examples/multi.flat.txt +0 -23
- data/examples/multi.graph.html +0 -760
- data/examples/multi.grind.dat +0 -114
- data/examples/multi.stack.html +0 -547
- data/examples/stack.html +0 -547
- data/ext/ruby_prof/rp_measure.c +0 -40
- data/ext/ruby_prof/rp_measure.h +0 -45
- data/ext/ruby_prof/rp_measure_cpu_time.c +0 -136
- data/ext/ruby_prof/rp_measure_gc_runs.c +0 -73
- data/ext/ruby_prof/rp_measure_gc_time.c +0 -60
- data/lib/ruby-prof/aggregate_call_info.rb +0 -76
- data/lib/ruby-prof/assets/call_stack_printer.css.html +0 -117
- data/lib/ruby-prof/assets/call_stack_printer.js.html +0 -385
- data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -83
- data/lib/ruby-prof/profile/exclude_common_methods.rb +0 -207
- data/lib/ruby-prof/profile/legacy_method_elimination.rb +0 -50
- data/test/aggregate_test.rb +0 -136
- data/test/block_test.rb +0 -74
- data/test/call_info_test.rb +0 -78
- data/test/issue137_test.rb +0 -63
- data/test/measure_cpu_time_test.rb +0 -212
- data/test/measure_gc_runs_test.rb +0 -32
- data/test/measure_gc_time_test.rb +0 -36
- data/test/measure_memory_test.rb +0 -33
- data/test/method_elimination_test.rb +0 -84
- data/test/module_test.rb +0 -45
- data/test/stack_test.rb +0 -138
data/Rakefile
CHANGED
@@ -40,7 +40,7 @@ Rake::ExtensionTask.new do |ext|
|
|
40
40
|
ext.ext_dir = "ext/#{SO_NAME}"
|
41
41
|
ext.lib_dir = "lib/#{RUBY_VERSION}"
|
42
42
|
ext.cross_compile = true
|
43
|
-
ext.cross_platform = ['x86-
|
43
|
+
ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
|
44
44
|
end
|
45
45
|
|
46
46
|
# Rake task to build the default package
|
@@ -80,12 +80,9 @@ RDoc::Task.new("rdoc") do |rdoc|
|
|
80
80
|
rdoc.options << '--main' << 'README.rdoc'
|
81
81
|
rdoc.rdoc_files.include('bin/*',
|
82
82
|
'doc/*.rdoc',
|
83
|
-
'examples/flat.txt',
|
84
|
-
'examples/graph.txt',
|
85
|
-
'examples/graph.html',
|
86
83
|
'lib/**/*.rb',
|
87
|
-
'ext/ruby_prof
|
88
|
-
'ext/ruby_prof
|
84
|
+
'ext/ruby_prof/*.c',
|
85
|
+
'ext/ruby_prof/*.h',
|
89
86
|
'README.rdoc',
|
90
87
|
'LICENSE')
|
91
88
|
end
|
data/bin/ruby-prof
CHANGED
@@ -1,18 +1,5 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
|
3
|
-
# == Synopsis
|
4
|
-
#
|
5
|
-
# Profiles a Ruby program.
|
6
|
-
#
|
7
|
-
# == Usage
|
8
|
-
#
|
9
|
-
# ruby_prof [options] <script.rb> [--] [script-options]"
|
10
|
-
#
|
11
|
-
# Various options:
|
12
|
-
# run "$ ruby-prof --help" to see them
|
13
|
-
#
|
14
|
-
# See also the readme "reports" section for the various outputs
|
15
|
-
|
16
3
|
# First require ruby-prof
|
17
4
|
require 'rubygems'
|
18
5
|
require 'ruby-prof'
|
@@ -22,7 +9,68 @@ require 'ostruct'
|
|
22
9
|
require 'optparse'
|
23
10
|
|
24
11
|
module RubyProf
|
12
|
+
# == Synopsis
|
13
|
+
#
|
14
|
+
# Profiles a Ruby program.
|
15
|
+
#
|
16
|
+
# == Usage
|
17
|
+
#
|
18
|
+
# ruby_prof [options] <script.rb> [--] [script-options]
|
19
|
+
#
|
20
|
+
# Options:
|
21
|
+
# -p, --printer=printer Select a printer:
|
22
|
+
# flat - Prints a flat profile as text (default).
|
23
|
+
# graph - Prints a graph profile as text.
|
24
|
+
# graph_html - Prints a graph profile as html.
|
25
|
+
# call_tree - format for KCacheGrind
|
26
|
+
# call_stack - prints a HTML visualization of the call tree
|
27
|
+
# dot - Prints a graph profile as a dot file
|
28
|
+
# multi - Creates several reports in output directory
|
29
|
+
#
|
30
|
+
# -m, --min_percent=min_percent The minimum percent a method must take before
|
31
|
+
# being included in output reports. This option is not supported for call tree reports.
|
32
|
+
#
|
33
|
+
# -f, --file=path Output results to a file instead of standard out.
|
34
|
+
#
|
35
|
+
# --mode=measure_mode Select what ruby-prof should measure:
|
36
|
+
# wall - Wall time (default)
|
37
|
+
# process - Process time
|
38
|
+
# allocations - Object allocations
|
39
|
+
# memory - Allocated memory
|
40
|
+
#
|
41
|
+
# -s, --sort=sort_mode Select how ruby-prof results should be sorted:
|
42
|
+
# total - Total time
|
43
|
+
# self - Self time
|
44
|
+
# wait - Wait time
|
45
|
+
# child - Child time
|
46
|
+
#
|
47
|
+
# --replace-progname Replace $0 when loading the .rb files.
|
48
|
+
#
|
49
|
+
# --specialized-instruction Turn on specified instruction.
|
50
|
+
#
|
51
|
+
# -v Show version, set $VERBOSE to true, profile script if option given
|
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
|
+
#
|
25
72
|
class Cmd
|
73
|
+
# :enddoc:
|
26
74
|
attr_accessor :options
|
27
75
|
|
28
76
|
def initialize
|
@@ -56,7 +104,6 @@ module RubyProf
|
|
56
104
|
opts.on('-p printer', '--printer=printer', [:flat, :flat_with_line_numbers, :graph, :graph_html, :call_tree, :call_stack, :dot, :multi],
|
57
105
|
'Select a printer:',
|
58
106
|
' flat - Prints a flat profile as text (default).',
|
59
|
-
' flat_with_line_numbers - same as flat, with line numbers.',
|
60
107
|
' graph - Prints a graph profile as text.',
|
61
108
|
' graph_html - Prints a graph profile as html.',
|
62
109
|
' call_tree - format for KCacheGrind',
|
@@ -65,12 +112,9 @@ module RubyProf
|
|
65
112
|
' multi - Creates several reports in output directory'
|
66
113
|
) do |printer|
|
67
114
|
|
68
|
-
|
69
115
|
case printer
|
70
116
|
when :flat
|
71
117
|
options.printer = RubyProf::FlatPrinter
|
72
|
-
when :flat_with_line_numbers
|
73
|
-
options.printer = RubyProf::FlatPrinterWithLineNumbers
|
74
118
|
when :graph
|
75
119
|
options.printer = RubyProf::GraphPrinter
|
76
120
|
when :graph_html
|
@@ -89,7 +133,7 @@ module RubyProf
|
|
89
133
|
opts.on('-m min_percent', '--min_percent=min_percent', Float,
|
90
134
|
'The minimum percent a method must take before ',
|
91
135
|
' being included in output reports.',
|
92
|
-
'
|
136
|
+
' This option is not supported for call tree.') do |min_percent|
|
93
137
|
options.min_percent = min_percent
|
94
138
|
end
|
95
139
|
|
@@ -100,31 +144,22 @@ module RubyProf
|
|
100
144
|
end
|
101
145
|
|
102
146
|
opts.on('--mode=measure_mode',
|
103
|
-
[:process, :wall, :
|
147
|
+
[:process, :wall, :allocations, :memory],
|
104
148
|
'Select what ruby-prof should measure:',
|
105
149
|
' wall - Wall time (default).',
|
106
150
|
' process - Process time.',
|
107
|
-
' cpu - CPU time (Pentium and PowerPCs only).',
|
108
151
|
' allocations - Object allocations (requires patched Ruby interpreter).',
|
109
|
-
' memory - Allocated memory in KB (requires patched Ruby interpreter).'
|
110
|
-
' gc_runs - Number of garbage collections (requires patched Ruby interpreter).',
|
111
|
-
' gc_time - Time spent in garbage collection (requires patched Ruby interpreter).') do |measure_mode|
|
152
|
+
' memory - Allocated memory in KB (requires patched Ruby interpreter).') do |measure_mode|
|
112
153
|
|
113
154
|
case measure_mode
|
114
155
|
when :wall
|
115
156
|
options.measure_mode = RubyProf::WALL_TIME
|
116
157
|
when :process
|
117
158
|
options.measure_mode = RubyProf::PROCESS_TIME
|
118
|
-
when :cpu
|
119
|
-
options.measure_mode = RubyProf::CPU_TIME
|
120
159
|
when :allocations
|
121
160
|
options.measure_mode = RubyProf::ALLOCATIONS
|
122
161
|
when :memory
|
123
162
|
options.measure_mode = RubyProf::MEMORY
|
124
|
-
when :gc_runs
|
125
|
-
options.measure_mode = RubyProf::GC_RUNS
|
126
|
-
when :gc_time
|
127
|
-
options.measure_mode = RubyProf::GC_TIME
|
128
163
|
end
|
129
164
|
end
|
130
165
|
|
@@ -184,7 +219,7 @@ module RubyProf
|
|
184
219
|
options.pre_execs << code
|
185
220
|
end
|
186
221
|
|
187
|
-
opts.on('-x regexp', '--exclude regexp', 'exclude methods by regexp (see method elimination)') do|meth|
|
222
|
+
opts.on('-x regexp', '--exclude regexp', 'exclude methods by regexp (see method elimination)') do |meth|
|
188
223
|
options.eliminate_methods ||= []
|
189
224
|
options.eliminate_methods << Regexp.new(meth)
|
190
225
|
end
|
data/ext/ruby_prof/extconf.rb
CHANGED
@@ -5,34 +5,16 @@ if RUBY_ENGINE != "ruby"
|
|
5
5
|
exit(1)
|
6
6
|
end
|
7
7
|
|
8
|
-
if RUBY_VERSION <
|
9
|
-
STDERR.puts("\n\n***** Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to
|
8
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4.0')
|
9
|
+
STDERR.puts("\n\n***** Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to 2.3 or higher. *****\n\n")
|
10
10
|
exit(1)
|
11
11
|
end
|
12
12
|
|
13
13
|
# For the love of bitfields...
|
14
14
|
$CFLAGS += ' -std=c99'
|
15
15
|
|
16
|
-
#
|
17
|
-
|
18
|
-
have_func("rb_gc_count")
|
19
|
-
have_func("rb_remove_event_hook_with_data")
|
20
|
-
|
21
|
-
# Alexander Dymo GC patch
|
22
|
-
have_func("rb_os_allocated_objects")
|
23
|
-
have_func("rb_gc_allocated_size")
|
24
|
-
|
25
|
-
# Stefan Kaes GC patches
|
26
|
-
have_func("rb_gc_collections")
|
27
|
-
have_func("rb_gc_time")
|
28
|
-
# for ruby 2.1
|
29
|
-
have_func("rb_gc_total_time")
|
30
|
-
have_func("rb_gc_total_mallocs")
|
31
|
-
have_func("rb_gc_total_malloced_bytes")
|
32
|
-
|
33
|
-
# Lloyd Hilaiel's heap info patch
|
34
|
-
have_func("rb_heap_total_mem")
|
35
|
-
have_func("rb_gc_heap_info")
|
16
|
+
# And since we are using C99
|
17
|
+
CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
|
36
18
|
|
37
19
|
def add_define(name, value = nil)
|
38
20
|
if value
|
@@ -46,23 +28,9 @@ def windows?
|
|
46
28
|
RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
47
29
|
end
|
48
30
|
|
49
|
-
if !windows? && RUBY_PLATFORM !~ /(darwin|openbsd)/
|
50
|
-
$LDFLAGS += " -lrt" # for clock_gettime
|
51
|
-
end
|
52
31
|
add_define("RUBY_PROF_RUBY_VERSION", RUBY_VERSION.split('.')[0..2].inject(0){|v,d| v*100+d.to_i})
|
53
32
|
|
54
|
-
#
|
55
|
-
|
56
|
-
require 'set'
|
57
|
-
threads = Set.new
|
58
|
-
set_trace_func lambda { |*args| threads << Thread.current.object_id }
|
59
|
-
Thread.new{1}.join
|
60
|
-
set_trace_func nil
|
61
|
-
if threads.size < 2
|
62
|
-
# if we end up here, ruby does not automatically activate tracing in spawned threads
|
63
|
-
STDERR.puts("Ruby #{RUBY_VERSION} does not activate tracing in spawned threads. Consider upgrading.")
|
64
|
-
exit(1)
|
65
|
-
end
|
66
|
-
end
|
33
|
+
# This function was added in Ruby 2.5, so once Ruby 2.4 is no longer supported this can be removed
|
34
|
+
have_func('rb_tracearg_callee_id', ["ruby.h"])
|
67
35
|
|
68
36
|
create_makefile("ruby_prof")
|
@@ -0,0 +1,279 @@
|
|
1
|
+
/* Copyright (C) 2005-2013 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_allocation.h"
|
5
|
+
|
6
|
+
VALUE cRpAllocation;
|
7
|
+
|
8
|
+
prof_allocation_t*
|
9
|
+
allocations_table_lookup(st_table *table, st_data_t key)
|
10
|
+
{
|
11
|
+
prof_allocation_t* result = NULL;
|
12
|
+
st_data_t value;
|
13
|
+
if (st_lookup(table, key, &value))
|
14
|
+
{
|
15
|
+
result = (prof_allocation_t*)value;
|
16
|
+
}
|
17
|
+
|
18
|
+
return result;
|
19
|
+
}
|
20
|
+
|
21
|
+
void
|
22
|
+
allocations_table_insert(st_table *table, st_data_t key, prof_allocation_t * allocation)
|
23
|
+
{
|
24
|
+
st_insert(table, (st_data_t)key, (st_data_t)allocation);
|
25
|
+
}
|
26
|
+
|
27
|
+
st_data_t
|
28
|
+
allocations_key(VALUE klass, int source_line)
|
29
|
+
{
|
30
|
+
return (klass << 4) + source_line;
|
31
|
+
}
|
32
|
+
|
33
|
+
/* ====== prof_allocation_t ====== */
|
34
|
+
prof_allocation_t*
|
35
|
+
prof_allocation_create(void)
|
36
|
+
{
|
37
|
+
prof_allocation_t *result = ALLOC(prof_allocation_t);
|
38
|
+
result->count = 0;
|
39
|
+
result->klass = Qnil;
|
40
|
+
result->klass_name = Qnil;
|
41
|
+
result->object = Qnil;
|
42
|
+
result->memory = 0;
|
43
|
+
result->source_line = 0;
|
44
|
+
result->source_file = Qnil;
|
45
|
+
result->key = 0;
|
46
|
+
|
47
|
+
return result;
|
48
|
+
}
|
49
|
+
|
50
|
+
prof_allocation_t*
|
51
|
+
prof_allocate_increment(prof_method_t* method, rb_trace_arg_t* trace_arg)
|
52
|
+
{
|
53
|
+
VALUE object = rb_tracearg_object(trace_arg);
|
54
|
+
if (BUILTIN_TYPE(object) == T_IMEMO)
|
55
|
+
return NULL;
|
56
|
+
|
57
|
+
VALUE klass = rb_obj_class(object);
|
58
|
+
|
59
|
+
int source_line = FIX2INT(rb_tracearg_lineno(trace_arg));
|
60
|
+
st_data_t key = allocations_key(klass, source_line);
|
61
|
+
|
62
|
+
prof_allocation_t* allocation = allocations_table_lookup(method->allocations_table, key);
|
63
|
+
if (!allocation)
|
64
|
+
{
|
65
|
+
allocation = prof_allocation_create();
|
66
|
+
allocation->source_line = source_line;
|
67
|
+
allocation->source_file = rb_tracearg_path(trace_arg);
|
68
|
+
allocation->klass_flags = 0;
|
69
|
+
allocation->klass = resolve_klass(klass, &allocation->klass_flags);
|
70
|
+
|
71
|
+
allocation->key = key;
|
72
|
+
allocations_table_insert(method->allocations_table, key, allocation);
|
73
|
+
}
|
74
|
+
|
75
|
+
allocation->count++;
|
76
|
+
allocation->memory += rb_obj_memsize_of(object);
|
77
|
+
|
78
|
+
return allocation;
|
79
|
+
}
|
80
|
+
|
81
|
+
static void
|
82
|
+
prof_allocation_ruby_gc_free(void *data)
|
83
|
+
{
|
84
|
+
prof_allocation_t* allocation = (prof_allocation_t*)data;
|
85
|
+
|
86
|
+
/* Has this allocation object been accessed by Ruby? If
|
87
|
+
yes clean it up so to avoid a segmentation fault. */
|
88
|
+
if (allocation->object != Qnil)
|
89
|
+
{
|
90
|
+
RDATA(allocation->object)->dmark = NULL;
|
91
|
+
RDATA(allocation->object)->dfree = NULL;
|
92
|
+
RDATA(allocation->object)->data = NULL;
|
93
|
+
allocation->object = Qnil;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
void
|
98
|
+
prof_allocation_free(prof_allocation_t* allocation)
|
99
|
+
{
|
100
|
+
prof_allocation_ruby_gc_free(allocation);
|
101
|
+
xfree(allocation);
|
102
|
+
}
|
103
|
+
|
104
|
+
size_t
|
105
|
+
prof_allocation_size(const void* data)
|
106
|
+
{
|
107
|
+
return sizeof(prof_allocation_t);
|
108
|
+
}
|
109
|
+
|
110
|
+
void
|
111
|
+
prof_allocation_mark(void *data)
|
112
|
+
{
|
113
|
+
prof_allocation_t* allocation = (prof_allocation_t*)data;
|
114
|
+
if (allocation->klass != Qnil)
|
115
|
+
rb_gc_mark(allocation->klass);
|
116
|
+
|
117
|
+
if (allocation->klass_name != Qnil)
|
118
|
+
rb_gc_mark(allocation->klass_name);
|
119
|
+
|
120
|
+
if (allocation->object != Qnil)
|
121
|
+
rb_gc_mark(allocation->object);
|
122
|
+
|
123
|
+
if (allocation->source_file != Qnil)
|
124
|
+
rb_gc_mark(allocation->source_file);
|
125
|
+
}
|
126
|
+
|
127
|
+
VALUE
|
128
|
+
prof_allocation_wrap(prof_allocation_t *allocation)
|
129
|
+
{
|
130
|
+
if (allocation->object == Qnil)
|
131
|
+
{
|
132
|
+
allocation->object = Data_Wrap_Struct(cRpAllocation, prof_allocation_mark , prof_allocation_ruby_gc_free, allocation);
|
133
|
+
}
|
134
|
+
return allocation->object;
|
135
|
+
}
|
136
|
+
|
137
|
+
static VALUE
|
138
|
+
prof_allocation_allocate(VALUE klass)
|
139
|
+
{
|
140
|
+
prof_allocation_t* allocation = prof_allocation_create();
|
141
|
+
allocation->object = prof_allocation_wrap(allocation);
|
142
|
+
return allocation->object;
|
143
|
+
}
|
144
|
+
|
145
|
+
prof_allocation_t*
|
146
|
+
prof_allocation_get(VALUE self)
|
147
|
+
{
|
148
|
+
/* Can't use Data_Get_Struct because that triggers the event hook
|
149
|
+
ending up in endless recursion. */
|
150
|
+
prof_allocation_t* result = DATA_PTR(self);
|
151
|
+
if (!result)
|
152
|
+
rb_raise(rb_eRuntimeError, "This RubyProf::Allocation instance has already been freed, likely because its profile has been freed.");
|
153
|
+
|
154
|
+
return result;
|
155
|
+
}
|
156
|
+
|
157
|
+
/* call-seq:
|
158
|
+
klass -> Class
|
159
|
+
|
160
|
+
Returns the type of Class being allocated. */
|
161
|
+
static VALUE
|
162
|
+
prof_allocation_klass_name(VALUE self)
|
163
|
+
{
|
164
|
+
prof_allocation_t* allocation = prof_allocation_get(self);
|
165
|
+
|
166
|
+
if (allocation->klass_name == Qnil)
|
167
|
+
allocation->klass_name = resolve_klass_name(allocation->klass, &allocation->klass_flags);
|
168
|
+
|
169
|
+
return allocation->klass_name;
|
170
|
+
}
|
171
|
+
|
172
|
+
/* call-seq:
|
173
|
+
klass_flags -> integer
|
174
|
+
|
175
|
+
Returns the klass flags */
|
176
|
+
|
177
|
+
static VALUE
|
178
|
+
prof_allocation_klass_flags(VALUE self)
|
179
|
+
{
|
180
|
+
prof_allocation_t* allocation = prof_allocation_get(self);
|
181
|
+
return INT2FIX(allocation->klass_flags);
|
182
|
+
}
|
183
|
+
|
184
|
+
/* call-seq:
|
185
|
+
source_file -> string
|
186
|
+
|
187
|
+
Returns the the line number where objects were allocated. */
|
188
|
+
static VALUE
|
189
|
+
prof_allocation_source_file(VALUE self)
|
190
|
+
{
|
191
|
+
prof_allocation_t* allocation = prof_allocation_get(self);
|
192
|
+
return allocation->source_file;
|
193
|
+
}
|
194
|
+
|
195
|
+
/* call-seq:
|
196
|
+
line -> number
|
197
|
+
|
198
|
+
Returns the the line number where objects were allocated. */
|
199
|
+
static VALUE
|
200
|
+
prof_allocation_source_line(VALUE self)
|
201
|
+
{
|
202
|
+
prof_allocation_t* allocation = prof_allocation_get(self);
|
203
|
+
return INT2FIX(allocation->source_line);
|
204
|
+
}
|
205
|
+
|
206
|
+
/* call-seq:
|
207
|
+
count -> number
|
208
|
+
|
209
|
+
Returns the number of times this class has been allocated. */
|
210
|
+
static VALUE
|
211
|
+
prof_allocation_count(VALUE self)
|
212
|
+
{
|
213
|
+
prof_allocation_t* allocation = prof_allocation_get(self);
|
214
|
+
return INT2FIX(allocation->count);
|
215
|
+
}
|
216
|
+
|
217
|
+
/* call-seq:
|
218
|
+
memory -> number
|
219
|
+
|
220
|
+
Returns the amount of memory allocated. */
|
221
|
+
static VALUE
|
222
|
+
prof_allocation_memory(VALUE self)
|
223
|
+
{
|
224
|
+
prof_allocation_t* allocation = prof_allocation_get(self);
|
225
|
+
return ULL2NUM(allocation->memory);
|
226
|
+
}
|
227
|
+
|
228
|
+
/* :nodoc: */
|
229
|
+
static VALUE
|
230
|
+
prof_allocation_dump(VALUE self)
|
231
|
+
{
|
232
|
+
prof_allocation_t* allocation = DATA_PTR(self);
|
233
|
+
|
234
|
+
VALUE result = rb_hash_new();
|
235
|
+
|
236
|
+
rb_hash_aset(result, ID2SYM(rb_intern("key")), INT2FIX(allocation->key));
|
237
|
+
rb_hash_aset(result, ID2SYM(rb_intern("klass_name")), prof_allocation_klass_name(self));
|
238
|
+
rb_hash_aset(result, ID2SYM(rb_intern("klass_flags")), INT2FIX(allocation->klass_flags));
|
239
|
+
rb_hash_aset(result, ID2SYM(rb_intern("source_file")), allocation->source_file);
|
240
|
+
rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(allocation->source_line));
|
241
|
+
rb_hash_aset(result, ID2SYM(rb_intern("count")), INT2FIX(allocation->count));
|
242
|
+
rb_hash_aset(result, ID2SYM(rb_intern("memory")), LONG2FIX(allocation->memory));
|
243
|
+
|
244
|
+
return result;
|
245
|
+
}
|
246
|
+
|
247
|
+
/* :nodoc: */
|
248
|
+
static VALUE
|
249
|
+
prof_allocation_load(VALUE self, VALUE data)
|
250
|
+
{
|
251
|
+
prof_allocation_t* allocation = DATA_PTR(self);
|
252
|
+
allocation->object = self;
|
253
|
+
|
254
|
+
allocation->key = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
|
255
|
+
allocation->klass_name = rb_hash_aref(data, ID2SYM(rb_intern("klass_name")));
|
256
|
+
allocation->klass_flags = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("klass_flags"))));
|
257
|
+
allocation->source_file = rb_hash_aref(data, ID2SYM(rb_intern("source_file")));
|
258
|
+
allocation->source_line = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("source_line"))));
|
259
|
+
allocation->count = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("count"))));
|
260
|
+
allocation->memory = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("memory"))));
|
261
|
+
|
262
|
+
return data;
|
263
|
+
}
|
264
|
+
|
265
|
+
void rp_init_allocation(void)
|
266
|
+
{
|
267
|
+
cRpAllocation = rb_define_class_under(mProf, "Allocation", rb_cData);
|
268
|
+
rb_undef_method(CLASS_OF(cRpAllocation), "new");
|
269
|
+
rb_define_alloc_func(cRpAllocation, prof_allocation_allocate);
|
270
|
+
|
271
|
+
rb_define_method(cRpAllocation, "klass_name", prof_allocation_klass_name, 0);
|
272
|
+
rb_define_method(cRpAllocation, "klass_flags", prof_allocation_klass_flags, 0);
|
273
|
+
rb_define_method(cRpAllocation, "source_file", prof_allocation_source_file, 0);
|
274
|
+
rb_define_method(cRpAllocation, "line", prof_allocation_source_line, 0);
|
275
|
+
rb_define_method(cRpAllocation, "count", prof_allocation_count, 0);
|
276
|
+
rb_define_method(cRpAllocation, "memory", prof_allocation_memory, 0);
|
277
|
+
rb_define_method(cRpAllocation, "_dump_data", prof_allocation_dump, 0);
|
278
|
+
rb_define_method(cRpAllocation, "_load_data", prof_allocation_load, 1);
|
279
|
+
}
|