ruby-prof 0.18.0-x64-mingw32 → 1.1.0-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|