ruby-prof 0.18.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +23 -0
  3. data/LICENSE +2 -2
  4. data/README.rdoc +1 -483
  5. data/Rakefile +3 -6
  6. data/bin/ruby-prof +65 -30
  7. data/ext/ruby_prof/extconf.rb +6 -38
  8. data/ext/ruby_prof/rp_allocation.c +292 -0
  9. data/ext/ruby_prof/rp_allocation.h +31 -0
  10. data/ext/ruby_prof/rp_call_info.c +137 -279
  11. data/ext/ruby_prof/rp_call_info.h +16 -34
  12. data/ext/ruby_prof/rp_measure_allocations.c +25 -49
  13. data/ext/ruby_prof/rp_measure_memory.c +21 -56
  14. data/ext/ruby_prof/rp_measure_process_time.c +28 -36
  15. data/ext/ruby_prof/rp_measure_wall_time.c +36 -19
  16. data/ext/ruby_prof/rp_measurement.c +236 -0
  17. data/ext/ruby_prof/rp_measurement.h +49 -0
  18. data/ext/ruby_prof/rp_method.c +395 -383
  19. data/ext/ruby_prof/rp_method.h +34 -39
  20. data/ext/ruby_prof/rp_profile.c +881 -0
  21. data/ext/ruby_prof/rp_profile.h +36 -0
  22. data/ext/ruby_prof/rp_stack.c +103 -80
  23. data/ext/ruby_prof/rp_stack.h +5 -12
  24. data/ext/ruby_prof/rp_thread.c +149 -88
  25. data/ext/ruby_prof/rp_thread.h +15 -6
  26. data/ext/ruby_prof/ruby_prof.c +11 -757
  27. data/ext/ruby_prof/ruby_prof.h +4 -47
  28. data/ext/ruby_prof/vc/ruby_prof.vcxproj +10 -8
  29. data/lib/ruby-prof.rb +2 -17
  30. data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
  31. data/lib/ruby-prof/call_info.rb +35 -93
  32. data/lib/ruby-prof/call_info_visitor.rb +19 -21
  33. data/lib/ruby-prof/compatibility.rb +37 -107
  34. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  35. data/lib/ruby-prof/measurement.rb +14 -0
  36. data/lib/ruby-prof/method_info.rb +52 -83
  37. data/lib/ruby-prof/printers/abstract_printer.rb +66 -52
  38. data/lib/ruby-prof/printers/call_info_printer.rb +13 -3
  39. data/lib/ruby-prof/printers/call_stack_printer.rb +32 -28
  40. data/lib/ruby-prof/printers/call_tree_printer.rb +20 -12
  41. data/lib/ruby-prof/printers/dot_printer.rb +5 -5
  42. data/lib/ruby-prof/printers/flat_printer.rb +6 -24
  43. data/lib/ruby-prof/printers/graph_html_printer.rb +7 -192
  44. data/lib/ruby-prof/printers/graph_printer.rb +13 -15
  45. data/lib/ruby-prof/printers/multi_printer.rb +66 -23
  46. data/lib/ruby-prof/profile.rb +10 -3
  47. data/lib/ruby-prof/rack.rb +0 -3
  48. data/lib/ruby-prof/thread.rb +12 -12
  49. data/lib/ruby-prof/version.rb +1 -1
  50. data/ruby-prof.gemspec +2 -2
  51. data/test/abstract_printer_test.rb +0 -27
  52. data/test/alias_test.rb +129 -0
  53. data/test/basic_test.rb +41 -40
  54. data/test/call_info_visitor_test.rb +3 -3
  55. data/test/dynamic_method_test.rb +0 -2
  56. data/test/line_number_test.rb +120 -39
  57. data/test/marshal_test.rb +119 -0
  58. data/test/measure_allocations.rb +30 -0
  59. data/test/measure_allocations_test.rb +371 -12
  60. data/test/measure_allocations_trace_test.rb +385 -0
  61. data/test/measure_memory_trace_test.rb +756 -0
  62. data/test/measure_process_time_test.rb +821 -33
  63. data/test/measure_times.rb +54 -0
  64. data/test/measure_wall_time_test.rb +349 -145
  65. data/test/multi_printer_test.rb +1 -34
  66. data/test/parser_timings.rb +24 -0
  67. data/test/pause_resume_test.rb +5 -5
  68. data/test/prime.rb +2 -0
  69. data/test/printer_call_tree_test.rb +31 -0
  70. data/test/printer_flat_test.rb +68 -0
  71. data/test/printer_graph_html_test.rb +60 -0
  72. data/test/printer_graph_test.rb +41 -0
  73. data/test/printers_test.rb +32 -166
  74. data/test/printing_recursive_graph_test.rb +26 -72
  75. data/test/recursive_test.rb +72 -77
  76. data/test/stack_printer_test.rb +2 -15
  77. data/test/start_stop_test.rb +22 -25
  78. data/test/test_helper.rb +5 -248
  79. data/test/thread_test.rb +11 -54
  80. data/test/unique_call_path_test.rb +16 -28
  81. data/test/yarv_test.rb +1 -0
  82. metadata +24 -34
  83. data/examples/flat.txt +0 -50
  84. data/examples/graph.dot +0 -84
  85. data/examples/graph.html +0 -823
  86. data/examples/graph.txt +0 -139
  87. data/examples/multi.flat.txt +0 -23
  88. data/examples/multi.graph.html +0 -760
  89. data/examples/multi.grind.dat +0 -114
  90. data/examples/multi.stack.html +0 -547
  91. data/examples/stack.html +0 -547
  92. data/ext/ruby_prof/rp_measure.c +0 -40
  93. data/ext/ruby_prof/rp_measure.h +0 -45
  94. data/ext/ruby_prof/rp_measure_cpu_time.c +0 -136
  95. data/ext/ruby_prof/rp_measure_gc_runs.c +0 -73
  96. data/ext/ruby_prof/rp_measure_gc_time.c +0 -60
  97. data/lib/ruby-prof/aggregate_call_info.rb +0 -76
  98. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -83
  99. data/lib/ruby-prof/profile/exclude_common_methods.rb +0 -207
  100. data/lib/ruby-prof/profile/legacy_method_elimination.rb +0 -50
  101. data/test/aggregate_test.rb +0 -136
  102. data/test/block_test.rb +0 -74
  103. data/test/call_info_test.rb +0 -78
  104. data/test/fiber_test.rb +0 -79
  105. data/test/issue137_test.rb +0 -63
  106. data/test/measure_cpu_time_test.rb +0 -212
  107. data/test/measure_gc_runs_test.rb +0 -32
  108. data/test/measure_gc_time_test.rb +0 -36
  109. data/test/measure_memory_test.rb +0 -33
  110. data/test/method_elimination_test.rb +0 -84
  111. data/test/module_test.rb +0 -45
  112. 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-mswin32-60', 'x86-mingw32-60']
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/ruby_prof.c',
88
- 'ext/ruby_prof/measure_*.h',
84
+ 'ext/ruby_prof/*.c',
85
+ 'ext/ruby_prof/*.h',
89
86
  'README.rdoc',
90
87
  'LICENSE')
91
88
  end
@@ -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
- ' this option is not supported for call tree.') do |min_percent|
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, :cpu, :allocations, :memory, :gc_runs, :gc_time],
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
@@ -5,34 +5,16 @@ if RUBY_ENGINE != "ruby"
5
5
  exit(1)
6
6
  end
7
7
 
8
- if RUBY_VERSION < "1.9.3"
9
- STDERR.puts("\n\n***** Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to 1.9.3 or higher. *****\n\n")
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
- # standard ruby methods
17
- have_func("rb_gc_stat")
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
- # for ruby 1.9, determine whether threads inherit trace flags (latest 1.9.2 and later should work correctly)
55
- if RUBY_VERSION > "1.9"
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,292 @@
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 thread 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)->data = NULL;
91
+ RDATA(allocation->object)->dfree = NULL;
92
+ RDATA(allocation->object)->dmark = NULL;
93
+ }
94
+ allocation->object = Qnil;
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
+ static const rb_data_type_t allocation_type =
128
+ {
129
+ .wrap_struct_name = "Allocation",
130
+ .function =
131
+ {
132
+ .dmark = prof_allocation_mark,
133
+ .dfree = prof_allocation_ruby_gc_free,
134
+ .dsize = prof_allocation_size,
135
+ },
136
+ .data = NULL,
137
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
138
+ };
139
+
140
+ VALUE
141
+ prof_allocation_wrap(prof_allocation_t *allocation)
142
+ {
143
+ if (allocation->object == Qnil)
144
+ {
145
+ allocation->object = TypedData_Wrap_Struct(cRpAllocation, &allocation_type, allocation);
146
+ }
147
+ return allocation->object;
148
+ }
149
+
150
+ static VALUE
151
+ prof_allocation_allocate(VALUE klass)
152
+ {
153
+ prof_allocation_t* allocation = prof_allocation_create();
154
+ allocation->object = prof_allocation_wrap(allocation);
155
+ return allocation->object;
156
+ }
157
+
158
+ prof_allocation_t*
159
+ prof_allocation_get(VALUE self)
160
+ {
161
+ /* Can't use Data_Get_Struct because that triggers the event hook
162
+ ending up in endless recursion. */
163
+ prof_allocation_t* result = DATA_PTR(self);
164
+ if (!result)
165
+ rb_raise(rb_eRuntimeError, "This RubyProf::Allocation instance has already been freed, likely because its profile has been freed.");
166
+
167
+ return result;
168
+ }
169
+
170
+ /* call-seq:
171
+ klass -> Class
172
+
173
+ Returns the type of Class being allocated. */
174
+ static VALUE
175
+ prof_allocation_klass_name(VALUE self)
176
+ {
177
+ prof_allocation_t* allocation = prof_allocation_get(self);
178
+
179
+ if (allocation->klass_name == Qnil)
180
+ allocation->klass_name = resolve_klass_name(allocation->klass, &allocation->klass_flags);
181
+
182
+ return allocation->klass_name;
183
+ }
184
+
185
+ /* call-seq:
186
+ klass_flags -> integer
187
+
188
+ Returns the klass flags */
189
+
190
+ static VALUE
191
+ prof_allocation_klass_flags(VALUE self)
192
+ {
193
+ prof_allocation_t* allocation = prof_allocation_get(self);
194
+ return INT2FIX(allocation->klass_flags);
195
+ }
196
+
197
+ /* call-seq:
198
+ source_file -> string
199
+
200
+ Returns the the line number where objects were allocated. */
201
+ static VALUE
202
+ prof_allocation_source_file(VALUE self)
203
+ {
204
+ prof_allocation_t* allocation = prof_allocation_get(self);
205
+ return allocation->source_file;
206
+ }
207
+
208
+ /* call-seq:
209
+ line -> number
210
+
211
+ Returns the the line number where objects were allocated. */
212
+ static VALUE
213
+ prof_allocation_source_line(VALUE self)
214
+ {
215
+ prof_allocation_t* allocation = prof_allocation_get(self);
216
+ return INT2FIX(allocation->source_line);
217
+ }
218
+
219
+ /* call-seq:
220
+ count -> number
221
+
222
+ Returns the number of times this class has been allocated. */
223
+ static VALUE
224
+ prof_allocation_count(VALUE self)
225
+ {
226
+ prof_allocation_t* allocation = prof_allocation_get(self);
227
+ return INT2FIX(allocation->count);
228
+ }
229
+
230
+ /* call-seq:
231
+ memory -> number
232
+
233
+ Returns the amount of memory allocated. */
234
+ static VALUE
235
+ prof_allocation_memory(VALUE self)
236
+ {
237
+ prof_allocation_t* allocation = prof_allocation_get(self);
238
+ return ULL2NUM(allocation->memory);
239
+ }
240
+
241
+ /* :nodoc: */
242
+ static VALUE
243
+ prof_allocation_dump(VALUE self)
244
+ {
245
+ prof_allocation_t* allocation = DATA_PTR(self);
246
+
247
+ VALUE result = rb_hash_new();
248
+
249
+ rb_hash_aset(result, ID2SYM(rb_intern("key")), INT2FIX(allocation->key));
250
+ rb_hash_aset(result, ID2SYM(rb_intern("klass_name")), prof_allocation_klass_name(self));
251
+ rb_hash_aset(result, ID2SYM(rb_intern("klass_flags")), INT2FIX(allocation->klass_flags));
252
+ rb_hash_aset(result, ID2SYM(rb_intern("source_file")), allocation->source_file);
253
+ rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(allocation->source_line));
254
+ rb_hash_aset(result, ID2SYM(rb_intern("count")), INT2FIX(allocation->count));
255
+ rb_hash_aset(result, ID2SYM(rb_intern("memory")), LONG2FIX(allocation->memory));
256
+
257
+ return result;
258
+ }
259
+
260
+ /* :nodoc: */
261
+ static VALUE
262
+ prof_allocation_load(VALUE self, VALUE data)
263
+ {
264
+ prof_allocation_t* allocation = DATA_PTR(self);
265
+ allocation->object = self;
266
+
267
+ allocation->key = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
268
+ allocation->klass_name = rb_hash_aref(data, ID2SYM(rb_intern("klass_name")));
269
+ allocation->klass_flags = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("klass_flags"))));
270
+ allocation->source_file = rb_hash_aref(data, ID2SYM(rb_intern("source_file")));
271
+ allocation->source_line = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("source_line"))));
272
+ allocation->count = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("count"))));
273
+ allocation->memory = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("memory"))));
274
+
275
+ return data;
276
+ }
277
+
278
+ void rp_init_allocation(void)
279
+ {
280
+ cRpAllocation = rb_define_class_under(mProf, "Allocation", rb_cData);
281
+ rb_undef_method(CLASS_OF(cRpAllocation), "new");
282
+ rb_define_alloc_func(cRpAllocation, prof_allocation_allocate);
283
+
284
+ rb_define_method(cRpAllocation, "klass_name", prof_allocation_klass_name, 0);
285
+ rb_define_method(cRpAllocation, "klass_flags", prof_allocation_klass_flags, 0);
286
+ rb_define_method(cRpAllocation, "source_file", prof_allocation_source_file, 0);
287
+ rb_define_method(cRpAllocation, "line", prof_allocation_source_line, 0);
288
+ rb_define_method(cRpAllocation, "count", prof_allocation_count, 0);
289
+ rb_define_method(cRpAllocation, "memory", prof_allocation_memory, 0);
290
+ rb_define_method(cRpAllocation, "_dump_data", prof_allocation_dump, 0);
291
+ rb_define_method(cRpAllocation, "_load_data", prof_allocation_load, 1);
292
+ }