ruby-prof 0.17.0 → 0.18.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.
Files changed (185) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +500 -482
  3. data/LICENSE +24 -24
  4. data/README.rdoc +487 -485
  5. data/Rakefile +113 -113
  6. data/bin/ruby-prof +345 -345
  7. data/bin/ruby-prof-check-trace +45 -45
  8. data/examples/flat.txt +50 -50
  9. data/examples/graph.dot +84 -84
  10. data/examples/graph.html +823 -823
  11. data/examples/graph.txt +139 -139
  12. data/examples/multi.flat.txt +23 -23
  13. data/examples/multi.graph.html +760 -760
  14. data/examples/multi.grind.dat +114 -114
  15. data/examples/multi.stack.html +547 -547
  16. data/examples/stack.html +547 -547
  17. data/ext/ruby_prof/extconf.rb +68 -68
  18. data/ext/ruby_prof/rp_call_info.c +425 -425
  19. data/ext/ruby_prof/rp_call_info.h +53 -53
  20. data/ext/ruby_prof/rp_measure.c +40 -40
  21. data/ext/ruby_prof/rp_measure.h +45 -45
  22. data/ext/ruby_prof/rp_measure_allocations.c +76 -76
  23. data/ext/ruby_prof/rp_measure_cpu_time.c +136 -136
  24. data/ext/ruby_prof/rp_measure_gc_runs.c +73 -73
  25. data/ext/ruby_prof/rp_measure_gc_time.c +60 -60
  26. data/ext/ruby_prof/rp_measure_memory.c +77 -77
  27. data/ext/ruby_prof/rp_measure_process_time.c +71 -71
  28. data/ext/ruby_prof/rp_measure_wall_time.c +45 -45
  29. data/ext/ruby_prof/rp_method.c +630 -636
  30. data/ext/ruby_prof/rp_method.h +75 -75
  31. data/ext/ruby_prof/rp_stack.c +173 -173
  32. data/ext/ruby_prof/rp_stack.h +63 -63
  33. data/ext/ruby_prof/rp_thread.c +277 -276
  34. data/ext/ruby_prof/rp_thread.h +27 -27
  35. data/ext/ruby_prof/ruby_prof.c +794 -774
  36. data/ext/ruby_prof/ruby_prof.h +60 -59
  37. data/ext/ruby_prof/vc/ruby_prof.sln +20 -21
  38. data/ext/ruby_prof/vc/{ruby_prof_20.vcxproj → ruby_prof.vcxproj} +31 -0
  39. data/lib/ruby-prof.rb +68 -68
  40. data/lib/ruby-prof/aggregate_call_info.rb +76 -76
  41. data/lib/ruby-prof/assets/call_stack_printer.css.html +116 -116
  42. data/lib/ruby-prof/assets/call_stack_printer.js.html +384 -384
  43. data/lib/ruby-prof/call_info.rb +115 -115
  44. data/lib/ruby-prof/call_info_visitor.rb +40 -40
  45. data/lib/ruby-prof/compatibility.rb +179 -178
  46. data/lib/ruby-prof/method_info.rb +121 -121
  47. data/lib/ruby-prof/printers/abstract_printer.rb +104 -103
  48. data/lib/ruby-prof/printers/call_info_printer.rb +41 -41
  49. data/lib/ruby-prof/printers/call_stack_printer.rb +265 -265
  50. data/lib/ruby-prof/printers/call_tree_printer.rb +143 -143
  51. data/lib/ruby-prof/printers/dot_printer.rb +132 -132
  52. data/lib/ruby-prof/printers/flat_printer.rb +70 -70
  53. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +83 -83
  54. data/lib/ruby-prof/printers/graph_html_printer.rb +249 -249
  55. data/lib/ruby-prof/printers/graph_printer.rb +116 -116
  56. data/lib/ruby-prof/printers/multi_printer.rb +84 -84
  57. data/lib/ruby-prof/profile.rb +26 -26
  58. data/lib/ruby-prof/profile/exclude_common_methods.rb +207 -201
  59. data/lib/ruby-prof/profile/legacy_method_elimination.rb +50 -49
  60. data/lib/ruby-prof/rack.rb +174 -174
  61. data/lib/ruby-prof/task.rb +147 -147
  62. data/lib/ruby-prof/thread.rb +35 -35
  63. data/lib/ruby-prof/version.rb +3 -3
  64. data/lib/unprof.rb +10 -10
  65. data/ruby-prof.gemspec +58 -58
  66. data/test/abstract_printer_test.rb +53 -0
  67. data/test/aggregate_test.rb +136 -136
  68. data/test/basic_test.rb +128 -128
  69. data/test/block_test.rb +74 -74
  70. data/test/call_info_test.rb +78 -78
  71. data/test/call_info_visitor_test.rb +31 -31
  72. data/test/duplicate_names_test.rb +32 -32
  73. data/test/dynamic_method_test.rb +55 -55
  74. data/test/enumerable_test.rb +21 -21
  75. data/test/exceptions_test.rb +24 -16
  76. data/test/exclude_methods_test.rb +146 -146
  77. data/test/exclude_threads_test.rb +53 -53
  78. data/test/fiber_test.rb +79 -79
  79. data/test/issue137_test.rb +63 -63
  80. data/test/line_number_test.rb +80 -80
  81. data/test/measure_allocations_test.rb +26 -26
  82. data/test/measure_cpu_time_test.rb +212 -213
  83. data/test/measure_gc_runs_test.rb +32 -32
  84. data/test/measure_gc_time_test.rb +36 -36
  85. data/test/measure_memory_test.rb +33 -33
  86. data/test/measure_process_time_test.rb +61 -63
  87. data/test/measure_wall_time_test.rb +255 -255
  88. data/test/method_elimination_test.rb +84 -84
  89. data/test/module_test.rb +45 -45
  90. data/test/multi_printer_test.rb +104 -104
  91. data/test/no_method_class_test.rb +15 -15
  92. data/test/pause_resume_test.rb +166 -166
  93. data/test/prime.rb +54 -54
  94. data/test/printers_test.rb +275 -275
  95. data/test/printing_recursive_graph_test.rb +127 -127
  96. data/test/rack_test.rb +157 -157
  97. data/test/recursive_test.rb +215 -215
  98. data/test/singleton_test.rb +38 -38
  99. data/test/stack_printer_test.rb +77 -78
  100. data/test/stack_test.rb +138 -138
  101. data/test/start_stop_test.rb +112 -112
  102. data/test/test_helper.rb +267 -275
  103. data/test/thread_test.rb +187 -187
  104. data/test/unique_call_path_test.rb +202 -202
  105. data/test/yarv_test.rb +55 -55
  106. metadata +17 -96
  107. data/doc/LICENSE.html +0 -115
  108. data/doc/README_rdoc.html +0 -637
  109. data/doc/Rack.html +0 -96
  110. data/doc/Rack/RubyProf.html +0 -233
  111. data/doc/Rack/RubyProf/RackProfiler.html +0 -343
  112. data/doc/RubyProf.html +0 -974
  113. data/doc/RubyProf/AbstractPrinter.html +0 -625
  114. data/doc/RubyProf/AggregateCallInfo.html +0 -552
  115. data/doc/RubyProf/CallInfo.html +0 -579
  116. data/doc/RubyProf/CallInfoPrinter.html +0 -121
  117. data/doc/RubyProf/CallInfoVisitor.html +0 -199
  118. data/doc/RubyProf/CallStackPrinter.html +0 -1127
  119. data/doc/RubyProf/CallTreePrinter.html +0 -725
  120. data/doc/RubyProf/Cmd.html +0 -637
  121. data/doc/RubyProf/DeprecationWarnings.html +0 -148
  122. data/doc/RubyProf/DotPrinter.html +0 -258
  123. data/doc/RubyProf/FlatPrinter.html +0 -164
  124. data/doc/RubyProf/FlatPrinterWithLineNumbers.html +0 -210
  125. data/doc/RubyProf/GraphHtmlPrinter.html +0 -558
  126. data/doc/RubyProf/GraphPrinter.html +0 -140
  127. data/doc/RubyProf/MethodInfo.html +0 -676
  128. data/doc/RubyProf/MultiPrinter.html +0 -574
  129. data/doc/RubyProf/Profile.html +0 -908
  130. data/doc/RubyProf/Profile/ExcludeCommonMethods.html +0 -411
  131. data/doc/RubyProf/Profile/LegacyMethodElimination.html +0 -158
  132. data/doc/RubyProf/ProfileTask.html +0 -491
  133. data/doc/RubyProf/Thread.html +0 -275
  134. data/doc/created.rid +0 -33
  135. data/doc/css/fonts.css +0 -167
  136. data/doc/css/rdoc.css +0 -590
  137. data/doc/examples/flat_txt.html +0 -139
  138. data/doc/examples/graph_html.html +0 -910
  139. data/doc/examples/graph_txt.html +0 -248
  140. data/doc/fonts/Lato-Light.ttf +0 -0
  141. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  142. data/doc/fonts/Lato-Regular.ttf +0 -0
  143. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  144. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  145. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  146. data/doc/images/add.png +0 -0
  147. data/doc/images/arrow_up.png +0 -0
  148. data/doc/images/brick.png +0 -0
  149. data/doc/images/brick_link.png +0 -0
  150. data/doc/images/bug.png +0 -0
  151. data/doc/images/bullet_black.png +0 -0
  152. data/doc/images/bullet_toggle_minus.png +0 -0
  153. data/doc/images/bullet_toggle_plus.png +0 -0
  154. data/doc/images/date.png +0 -0
  155. data/doc/images/delete.png +0 -0
  156. data/doc/images/find.png +0 -0
  157. data/doc/images/loadingAnimation.gif +0 -0
  158. data/doc/images/macFFBgHack.png +0 -0
  159. data/doc/images/package.png +0 -0
  160. data/doc/images/page_green.png +0 -0
  161. data/doc/images/page_white_text.png +0 -0
  162. data/doc/images/page_white_width.png +0 -0
  163. data/doc/images/plugin.png +0 -0
  164. data/doc/images/ruby.png +0 -0
  165. data/doc/images/tag_blue.png +0 -0
  166. data/doc/images/tag_green.png +0 -0
  167. data/doc/images/transparent.png +0 -0
  168. data/doc/images/wrench.png +0 -0
  169. data/doc/images/wrench_orange.png +0 -0
  170. data/doc/images/zoom.png +0 -0
  171. data/doc/index.html +0 -666
  172. data/doc/js/darkfish.js +0 -161
  173. data/doc/js/jquery.js +0 -4
  174. data/doc/js/navigation.js +0 -142
  175. data/doc/js/navigation.js.gz +0 -0
  176. data/doc/js/search.js +0 -109
  177. data/doc/js/search_index.js +0 -1
  178. data/doc/js/search_index.js.gz +0 -0
  179. data/doc/js/searcher.js +0 -229
  180. data/doc/js/searcher.js.gz +0 -0
  181. data/doc/table_of_contents.html +0 -1052
  182. data/examples/cachegrind.out.1 +0 -114
  183. data/examples/cachegrind.out.1.32313213 +0 -114
  184. data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +0 -108
  185. data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +0 -110
@@ -1,68 +1,68 @@
1
- require "mkmf"
2
-
3
- if RUBY_ENGINE != "ruby"
4
- STDERR.puts("\n\n***** This gem is MRI-specific. It does not support #{RUBY_ENGINE}. *****\n\n")
5
- exit(1)
6
- end
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")
10
- exit(1)
11
- end
12
-
13
- # For the love of bitfields...
14
- $CFLAGS += ' -std=c99'
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")
36
-
37
- def add_define(name, value = nil)
38
- if value
39
- $defs.push("-D#{name}=#{value}")
40
- else
41
- $defs.push("-D#{name}")
42
- end
43
- end
44
-
45
- def windows?
46
- RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
47
- end
48
-
49
- if !windows? && RUBY_PLATFORM !~ /(darwin|openbsd)/
50
- $LDFLAGS += " -lrt" # for clock_gettime
51
- end
52
- add_define("RUBY_PROF_RUBY_VERSION", RUBY_VERSION.split('.')[0..2].inject(0){|v,d| v*100+d.to_i})
53
-
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
67
-
68
- create_makefile("ruby_prof")
1
+ require "mkmf"
2
+
3
+ if RUBY_ENGINE != "ruby"
4
+ STDERR.puts("\n\n***** This gem is MRI-specific. It does not support #{RUBY_ENGINE}. *****\n\n")
5
+ exit(1)
6
+ end
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")
10
+ exit(1)
11
+ end
12
+
13
+ # For the love of bitfields...
14
+ $CFLAGS += ' -std=c99'
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")
36
+
37
+ def add_define(name, value = nil)
38
+ if value
39
+ $defs.push("-D#{name}=#{value}")
40
+ else
41
+ $defs.push("-D#{name}")
42
+ end
43
+ end
44
+
45
+ def windows?
46
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
47
+ end
48
+
49
+ if !windows? && RUBY_PLATFORM !~ /(darwin|openbsd)/
50
+ $LDFLAGS += " -lrt" # for clock_gettime
51
+ end
52
+ add_define("RUBY_PROF_RUBY_VERSION", RUBY_VERSION.split('.')[0..2].inject(0){|v,d| v*100+d.to_i})
53
+
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
67
+
68
+ create_makefile("ruby_prof")
@@ -1,425 +1,425 @@
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 "ruby_prof.h"
5
-
6
- #define INITIAL_CALL_INFOS_SIZE 2
7
-
8
- VALUE cCallInfo;
9
-
10
-
11
- // Forward declarations
12
- st_table * call_info_table_create();
13
-
14
-
15
- /* ======= prof_call_info_t ========*/
16
- prof_call_info_t *
17
- prof_call_info_create(prof_method_t* method, prof_call_info_t* parent)
18
- {
19
- prof_call_info_t *result = ALLOC(prof_call_info_t);
20
- result->object = Qnil;
21
- result->target = method;
22
- result->parent = parent;
23
- result->call_infos = call_info_table_create();
24
- result->children = Qnil;
25
-
26
- result->total_time = 0;
27
- result->self_time = 0;
28
- result->wait_time = 0;
29
-
30
- result->called = 0;
31
-
32
- result->recursive = 0;
33
- result->depth = 0;
34
- result->line = 0;
35
-
36
- return result;
37
- }
38
- static void
39
- prof_call_info_ruby_gc_free(prof_call_info_t *call_info)
40
- {
41
- /* Has this thread object been accessed by Ruby? If
42
- yes clean it up so to avoid a segmentation fault. */
43
- if (call_info->object != Qnil)
44
- {
45
- RDATA(call_info->object)->data = NULL;
46
- RDATA(call_info->object)->dfree = NULL;
47
- RDATA(call_info->object)->dmark = NULL;
48
- }
49
- call_info->object = Qnil;
50
- }
51
-
52
- static void
53
- prof_call_info_free(prof_call_info_t *call_info)
54
- {
55
- prof_call_info_ruby_gc_free(call_info);
56
- st_free_table(call_info->call_infos);
57
- xfree(call_info);
58
- }
59
-
60
- static void
61
- prof_call_info_mark(prof_call_info_t *call_info)
62
- {
63
- if (call_info->object)
64
- rb_gc_mark(call_info->object);
65
-
66
- if (call_info->children)
67
- rb_gc_mark(call_info->children);
68
-
69
- /* We don't mark the call info child table since that will be done
70
- via the appropriate method */
71
- }
72
-
73
- VALUE
74
- prof_call_info_wrap(prof_call_info_t *call_info)
75
- {
76
- if (call_info->object == Qnil)
77
- {
78
- call_info->object = Data_Wrap_Struct(cCallInfo, prof_call_info_mark, prof_call_info_ruby_gc_free, call_info);
79
- }
80
- return call_info->object;
81
- }
82
-
83
- static prof_call_info_t *
84
- prof_get_call_info(VALUE self)
85
- {
86
- /* Can't use Data_Get_Struct because that triggers the event hook
87
- ending up in endless recursion. */
88
- prof_call_info_t* result = DATA_PTR(self);
89
-
90
- if (!result)
91
- rb_raise(rb_eRuntimeError, "This RubyProf::CallInfo instance has already been freed, likely because its profile has been freed.");
92
-
93
- return result;
94
- }
95
-
96
- /* ======= Call Info Table ========*/
97
- st_table *
98
- call_info_table_create()
99
- {
100
- return st_init_table(&type_method_hash);
101
- }
102
-
103
- size_t
104
- call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val)
105
- {
106
- return st_insert(table, (st_data_t) key, (st_data_t) val);
107
- }
108
-
109
- prof_call_info_t *
110
- call_info_table_lookup(st_table *table, const prof_method_key_t *key)
111
- {
112
- st_data_t val;
113
- if (st_lookup(table, (st_data_t) key, &val))
114
- {
115
- return (prof_call_info_t *) val;
116
- }
117
- else
118
- {
119
- return NULL;
120
- }
121
- }
122
-
123
-
124
- /* ======= RubyProf::CallInfo ========*/
125
-
126
- /* Document-class: RubyProf::CallInfo
127
- RubyProf::CallInfo is a helper class used by RubyProf::MethodInfo
128
- to keep track of which child methods were called and how long
129
- they took to execute. */
130
-
131
-
132
- /* call-seq:
133
- called -> MethodInfo
134
-
135
- Returns the target method. */
136
- static VALUE
137
- prof_call_info_target(VALUE self)
138
- {
139
- /* Target is a pointer to a method_info - so we have to be careful
140
- about the GC. We will wrap the method_info but provide no
141
- free method so the underlying object is not freed twice! */
142
-
143
- prof_call_info_t *result = prof_get_call_info(self);
144
- return prof_method_wrap(result->target);
145
- }
146
-
147
- /* call-seq:
148
- called -> int
149
-
150
- Returns the total amount of times this method was called. */
151
- static VALUE
152
- prof_call_info_called(VALUE self)
153
- {
154
- prof_call_info_t *result = prof_get_call_info(self);
155
- return INT2NUM(result->called);
156
- }
157
-
158
- /* call-seq:
159
- called=n -> n
160
-
161
- Sets the call count to n. */
162
- static VALUE
163
- prof_call_info_set_called(VALUE self, VALUE called)
164
- {
165
- prof_call_info_t *result = prof_get_call_info(self);
166
- result->called = NUM2INT(called);
167
- return called;
168
- }
169
-
170
- /* call-seq:
171
- recursive? -> boolean
172
-
173
- Returns the true if this call info is a recursive invocation */
174
- static VALUE
175
- prof_call_info_recursive(VALUE self)
176
- {
177
- prof_call_info_t *result = prof_get_call_info(self);
178
- return result->recursive ? Qtrue : Qfalse;
179
- }
180
-
181
- /* call-seq:
182
- depth -> int
183
-
184
- returns the depth of this call info in the call graph */
185
- static VALUE
186
- prof_call_info_depth(VALUE self)
187
- {
188
- prof_call_info_t *result = prof_get_call_info(self);
189
- return rb_int_new(result->depth);
190
- }
191
-
192
- /* call-seq:
193
- line_no -> int
194
-
195
- returns the line number of the method */
196
- static VALUE
197
- prof_call_info_line(VALUE self)
198
- {
199
- prof_call_info_t *result = prof_get_call_info(self);
200
- return rb_int_new(result->line);
201
- }
202
-
203
- /* call-seq:
204
- total_time -> float
205
-
206
- Returns the total amount of time spent in this method and its children. */
207
- static VALUE
208
- prof_call_info_total_time(VALUE self)
209
- {
210
- prof_call_info_t *result = prof_get_call_info(self);
211
- return rb_float_new(result->total_time);
212
- }
213
-
214
- /* call-seq:
215
- add_total_time(call_info) -> nil
216
-
217
- adds total time time from call_info to self. */
218
- static VALUE
219
- prof_call_info_add_total_time(VALUE self, VALUE other)
220
- {
221
- prof_call_info_t *result = prof_get_call_info(self);
222
- prof_call_info_t *other_info = prof_get_call_info(other);
223
-
224
- result->total_time += other_info->total_time;
225
- return Qnil;
226
- }
227
-
228
- /* call-seq:
229
- self_time -> float
230
-
231
- Returns the total amount of time spent in this method. */
232
- static VALUE
233
- prof_call_info_self_time(VALUE self)
234
- {
235
- prof_call_info_t *result = prof_get_call_info(self);
236
-
237
- return rb_float_new(result->self_time);
238
- }
239
-
240
- /* call-seq:
241
- add_self_time(call_info) -> nil
242
-
243
- adds self time from call_info to self. */
244
- static VALUE
245
- prof_call_info_add_self_time(VALUE self, VALUE other)
246
- {
247
- prof_call_info_t *result = prof_get_call_info(self);
248
- prof_call_info_t *other_info = prof_get_call_info(other);
249
-
250
- result->self_time += other_info->self_time;
251
- return Qnil;
252
- }
253
-
254
- /* call-seq:
255
- wait_time -> float
256
-
257
- Returns the total amount of time this method waited for other threads. */
258
- static VALUE
259
- prof_call_info_wait_time(VALUE self)
260
- {
261
- prof_call_info_t *result = prof_get_call_info(self);
262
-
263
- return rb_float_new(result->wait_time);
264
- }
265
-
266
- /* call-seq:
267
- add_wait_time(call_info) -> nil
268
-
269
- adds wait time from call_info to self. */
270
-
271
- static VALUE
272
- prof_call_info_add_wait_time(VALUE self, VALUE other)
273
- {
274
- prof_call_info_t *result = prof_get_call_info(self);
275
- prof_call_info_t *other_info = prof_get_call_info(other);
276
-
277
- result->wait_time += other_info->wait_time;
278
- return Qnil;
279
- }
280
-
281
- /* call-seq:
282
- parent -> call_info
283
-
284
- Returns the call_infos parent call_info object (the method that called this method).*/
285
- static VALUE
286
- prof_call_info_parent(VALUE self)
287
- {
288
- prof_call_info_t *result = prof_get_call_info(self);
289
- if (result->parent)
290
- return prof_call_info_wrap(result->parent);
291
- else
292
- return Qnil;
293
- }
294
-
295
- /* call-seq:
296
- parent=new_parent -> new_parent
297
-
298
- Changes the parent of self to new_parent and returns it.*/
299
- static VALUE
300
- prof_call_info_set_parent(VALUE self, VALUE new_parent)
301
- {
302
- prof_call_info_t *result = prof_get_call_info(self);
303
- if (new_parent == Qnil)
304
- result->parent = NULL;
305
- else
306
- result->parent = prof_get_call_info(new_parent);
307
- return prof_call_info_parent(self);
308
- }
309
-
310
- static int
311
- prof_call_info_collect_children(st_data_t key, st_data_t value, st_data_t result)
312
- {
313
- prof_call_info_t *call_info = (prof_call_info_t *) value;
314
- VALUE arr = (VALUE) result;
315
- rb_ary_push(arr, prof_call_info_wrap(call_info));
316
- return ST_CONTINUE;
317
- }
318
-
319
- /* call-seq:
320
- children -> hash
321
-
322
- Returns an array of call info objects of methods that this method
323
- called (ie, children).*/
324
- static VALUE
325
- prof_call_info_children(VALUE self)
326
- {
327
- prof_call_info_t *call_info = prof_get_call_info(self);
328
- if (call_info->children == Qnil)
329
- {
330
- call_info->children = rb_ary_new();
331
- st_foreach(call_info->call_infos, prof_call_info_collect_children, call_info->children);
332
- }
333
- return call_info->children;
334
- }
335
-
336
- /* ======= Call Infos ========*/
337
- prof_call_infos_t*
338
- prof_call_infos_create()
339
- {
340
- prof_call_infos_t *result = ALLOC(prof_call_infos_t);
341
- result->start = ALLOC_N(prof_call_info_t*, INITIAL_CALL_INFOS_SIZE);
342
- result->end = result->start + INITIAL_CALL_INFOS_SIZE;
343
- result->ptr = result->start;
344
- result->object = Qnil;
345
- return result;
346
- }
347
-
348
- void
349
- prof_call_infos_mark(prof_call_infos_t *call_infos)
350
- {
351
- prof_call_info_t **call_info;
352
-
353
- if (call_infos->object)
354
- rb_gc_mark(call_infos->object);
355
-
356
- for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
357
- {
358
- prof_call_info_mark(*call_info);
359
- }
360
- }
361
-
362
- void
363
- prof_call_infos_free(prof_call_infos_t *call_infos)
364
- {
365
- prof_call_info_t **call_info;
366
-
367
- for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
368
- {
369
- prof_call_info_free(*call_info);
370
- }
371
- }
372
-
373
- void
374
- prof_add_call_info(prof_call_infos_t *call_infos, prof_call_info_t *call_info)
375
- {
376
- if (call_infos->ptr == call_infos->end)
377
- {
378
- size_t len = call_infos->ptr - call_infos->start;
379
- size_t new_capacity = (call_infos->end - call_infos->start) * 2;
380
- REALLOC_N(call_infos->start, prof_call_info_t*, new_capacity);
381
- call_infos->ptr = call_infos->start + len;
382
- call_infos->end = call_infos->start + new_capacity;
383
- }
384
- *call_infos->ptr = call_info;
385
- call_infos->ptr++;
386
- }
387
-
388
- VALUE
389
- prof_call_infos_wrap(prof_call_infos_t *call_infos)
390
- {
391
- if (call_infos->object == Qnil)
392
- {
393
- prof_call_info_t **i;
394
- call_infos->object = rb_ary_new();
395
- for(i=call_infos->start; i<call_infos->ptr; i++)
396
- {
397
- VALUE call_info = prof_call_info_wrap(*i);
398
- rb_ary_push(call_infos->object, call_info);
399
- }
400
- }
401
- return call_infos->object;
402
- }
403
-
404
- void rp_init_call_info()
405
- {
406
- /* CallInfo */
407
- cCallInfo = rb_define_class_under(mProf, "CallInfo", rb_cObject);
408
- rb_undef_method(CLASS_OF(cCallInfo), "new");
409
- rb_define_method(cCallInfo, "parent", prof_call_info_parent, 0);
410
- rb_define_method(cCallInfo, "parent=", prof_call_info_set_parent, 1);
411
- rb_define_method(cCallInfo, "children", prof_call_info_children, 0);
412
- rb_define_method(cCallInfo, "target", prof_call_info_target, 0);
413
- rb_define_method(cCallInfo, "called", prof_call_info_called, 0);
414
- rb_define_method(cCallInfo, "called=", prof_call_info_set_called, 1);
415
- rb_define_method(cCallInfo, "total_time", prof_call_info_total_time, 0);
416
- rb_define_method(cCallInfo, "add_total_time", prof_call_info_add_total_time, 1);
417
- rb_define_method(cCallInfo, "self_time", prof_call_info_self_time, 0);
418
- rb_define_method(cCallInfo, "add_self_time", prof_call_info_add_self_time, 1);
419
- rb_define_method(cCallInfo, "wait_time", prof_call_info_wait_time, 0);
420
- rb_define_method(cCallInfo, "add_wait_time", prof_call_info_add_wait_time, 1);
421
-
422
- rb_define_method(cCallInfo, "recursive?", prof_call_info_recursive, 0);
423
- rb_define_method(cCallInfo, "depth", prof_call_info_depth, 0);
424
- rb_define_method(cCallInfo, "line", prof_call_info_line, 0);
425
- }
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 "ruby_prof.h"
5
+
6
+ #define INITIAL_CALL_INFOS_SIZE 2
7
+
8
+ VALUE cCallInfo;
9
+
10
+
11
+ // Forward declarations
12
+ st_table * call_info_table_create();
13
+
14
+
15
+ /* ======= prof_call_info_t ========*/
16
+ prof_call_info_t *
17
+ prof_call_info_create(prof_method_t* method, prof_call_info_t* parent)
18
+ {
19
+ prof_call_info_t *result = ALLOC(prof_call_info_t);
20
+ result->object = Qnil;
21
+ result->target = method;
22
+ result->parent = parent;
23
+ result->call_infos = call_info_table_create();
24
+ result->children = Qnil;
25
+
26
+ result->total_time = 0;
27
+ result->self_time = 0;
28
+ result->wait_time = 0;
29
+
30
+ result->called = 0;
31
+
32
+ result->recursive = 0;
33
+ result->depth = 0;
34
+ result->line = 0;
35
+
36
+ return result;
37
+ }
38
+ static void
39
+ prof_call_info_ruby_gc_free(prof_call_info_t *call_info)
40
+ {
41
+ /* Has this thread object been accessed by Ruby? If
42
+ yes clean it up so to avoid a segmentation fault. */
43
+ if (call_info->object != Qnil)
44
+ {
45
+ RDATA(call_info->object)->data = NULL;
46
+ RDATA(call_info->object)->dfree = NULL;
47
+ RDATA(call_info->object)->dmark = NULL;
48
+ }
49
+ call_info->object = Qnil;
50
+ }
51
+
52
+ static void
53
+ prof_call_info_free(prof_call_info_t *call_info)
54
+ {
55
+ prof_call_info_ruby_gc_free(call_info);
56
+ st_free_table(call_info->call_infos);
57
+ xfree(call_info);
58
+ }
59
+
60
+ static void
61
+ prof_call_info_mark(prof_call_info_t *call_info)
62
+ {
63
+ if (call_info->object)
64
+ rb_gc_mark(call_info->object);
65
+
66
+ if (call_info->children)
67
+ rb_gc_mark(call_info->children);
68
+
69
+ /* We don't mark the call info child table since that will be done
70
+ via the appropriate method */
71
+ }
72
+
73
+ VALUE
74
+ prof_call_info_wrap(prof_call_info_t *call_info)
75
+ {
76
+ if (call_info->object == Qnil)
77
+ {
78
+ call_info->object = Data_Wrap_Struct(cCallInfo, prof_call_info_mark, prof_call_info_ruby_gc_free, call_info);
79
+ }
80
+ return call_info->object;
81
+ }
82
+
83
+ static prof_call_info_t *
84
+ prof_get_call_info(VALUE self)
85
+ {
86
+ /* Can't use Data_Get_Struct because that triggers the event hook
87
+ ending up in endless recursion. */
88
+ prof_call_info_t* result = DATA_PTR(self);
89
+
90
+ if (!result)
91
+ rb_raise(rb_eRuntimeError, "This RubyProf::CallInfo instance has already been freed, likely because its profile has been freed.");
92
+
93
+ return result;
94
+ }
95
+
96
+ /* ======= Call Info Table ========*/
97
+ st_table *
98
+ call_info_table_create()
99
+ {
100
+ return st_init_table(&type_method_hash);
101
+ }
102
+
103
+ size_t
104
+ call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val)
105
+ {
106
+ return st_insert(table, (st_data_t) key, (st_data_t) val);
107
+ }
108
+
109
+ prof_call_info_t *
110
+ call_info_table_lookup(st_table *table, const prof_method_key_t *key)
111
+ {
112
+ st_data_t val;
113
+ if (st_lookup(table, (st_data_t) key, &val))
114
+ {
115
+ return (prof_call_info_t *) val;
116
+ }
117
+ else
118
+ {
119
+ return NULL;
120
+ }
121
+ }
122
+
123
+
124
+ /* ======= RubyProf::CallInfo ========*/
125
+
126
+ /* Document-class: RubyProf::CallInfo
127
+ RubyProf::CallInfo is a helper class used by RubyProf::MethodInfo
128
+ to keep track of which child methods were called and how long
129
+ they took to execute. */
130
+
131
+
132
+ /* call-seq:
133
+ called -> MethodInfo
134
+
135
+ Returns the target method. */
136
+ static VALUE
137
+ prof_call_info_target(VALUE self)
138
+ {
139
+ /* Target is a pointer to a method_info - so we have to be careful
140
+ about the GC. We will wrap the method_info but provide no
141
+ free method so the underlying object is not freed twice! */
142
+
143
+ prof_call_info_t *result = prof_get_call_info(self);
144
+ return prof_method_wrap(result->target);
145
+ }
146
+
147
+ /* call-seq:
148
+ called -> int
149
+
150
+ Returns the total amount of times this method was called. */
151
+ static VALUE
152
+ prof_call_info_called(VALUE self)
153
+ {
154
+ prof_call_info_t *result = prof_get_call_info(self);
155
+ return INT2NUM(result->called);
156
+ }
157
+
158
+ /* call-seq:
159
+ called=n -> n
160
+
161
+ Sets the call count to n. */
162
+ static VALUE
163
+ prof_call_info_set_called(VALUE self, VALUE called)
164
+ {
165
+ prof_call_info_t *result = prof_get_call_info(self);
166
+ result->called = NUM2INT(called);
167
+ return called;
168
+ }
169
+
170
+ /* call-seq:
171
+ recursive? -> boolean
172
+
173
+ Returns the true if this call info is a recursive invocation */
174
+ static VALUE
175
+ prof_call_info_recursive(VALUE self)
176
+ {
177
+ prof_call_info_t *result = prof_get_call_info(self);
178
+ return result->recursive ? Qtrue : Qfalse;
179
+ }
180
+
181
+ /* call-seq:
182
+ depth -> int
183
+
184
+ returns the depth of this call info in the call graph */
185
+ static VALUE
186
+ prof_call_info_depth(VALUE self)
187
+ {
188
+ prof_call_info_t *result = prof_get_call_info(self);
189
+ return rb_int_new(result->depth);
190
+ }
191
+
192
+ /* call-seq:
193
+ line_no -> int
194
+
195
+ returns the line number of the method */
196
+ static VALUE
197
+ prof_call_info_line(VALUE self)
198
+ {
199
+ prof_call_info_t *result = prof_get_call_info(self);
200
+ return rb_int_new(result->line);
201
+ }
202
+
203
+ /* call-seq:
204
+ total_time -> float
205
+
206
+ Returns the total amount of time spent in this method and its children. */
207
+ static VALUE
208
+ prof_call_info_total_time(VALUE self)
209
+ {
210
+ prof_call_info_t *result = prof_get_call_info(self);
211
+ return rb_float_new(result->total_time);
212
+ }
213
+
214
+ /* call-seq:
215
+ add_total_time(call_info) -> nil
216
+
217
+ adds total time time from call_info to self. */
218
+ static VALUE
219
+ prof_call_info_add_total_time(VALUE self, VALUE other)
220
+ {
221
+ prof_call_info_t *result = prof_get_call_info(self);
222
+ prof_call_info_t *other_info = prof_get_call_info(other);
223
+
224
+ result->total_time += other_info->total_time;
225
+ return Qnil;
226
+ }
227
+
228
+ /* call-seq:
229
+ self_time -> float
230
+
231
+ Returns the total amount of time spent in this method. */
232
+ static VALUE
233
+ prof_call_info_self_time(VALUE self)
234
+ {
235
+ prof_call_info_t *result = prof_get_call_info(self);
236
+
237
+ return rb_float_new(result->self_time);
238
+ }
239
+
240
+ /* call-seq:
241
+ add_self_time(call_info) -> nil
242
+
243
+ adds self time from call_info to self. */
244
+ static VALUE
245
+ prof_call_info_add_self_time(VALUE self, VALUE other)
246
+ {
247
+ prof_call_info_t *result = prof_get_call_info(self);
248
+ prof_call_info_t *other_info = prof_get_call_info(other);
249
+
250
+ result->self_time += other_info->self_time;
251
+ return Qnil;
252
+ }
253
+
254
+ /* call-seq:
255
+ wait_time -> float
256
+
257
+ Returns the total amount of time this method waited for other threads. */
258
+ static VALUE
259
+ prof_call_info_wait_time(VALUE self)
260
+ {
261
+ prof_call_info_t *result = prof_get_call_info(self);
262
+
263
+ return rb_float_new(result->wait_time);
264
+ }
265
+
266
+ /* call-seq:
267
+ add_wait_time(call_info) -> nil
268
+
269
+ adds wait time from call_info to self. */
270
+
271
+ static VALUE
272
+ prof_call_info_add_wait_time(VALUE self, VALUE other)
273
+ {
274
+ prof_call_info_t *result = prof_get_call_info(self);
275
+ prof_call_info_t *other_info = prof_get_call_info(other);
276
+
277
+ result->wait_time += other_info->wait_time;
278
+ return Qnil;
279
+ }
280
+
281
+ /* call-seq:
282
+ parent -> call_info
283
+
284
+ Returns the call_infos parent call_info object (the method that called this method).*/
285
+ static VALUE
286
+ prof_call_info_parent(VALUE self)
287
+ {
288
+ prof_call_info_t *result = prof_get_call_info(self);
289
+ if (result->parent)
290
+ return prof_call_info_wrap(result->parent);
291
+ else
292
+ return Qnil;
293
+ }
294
+
295
+ /* call-seq:
296
+ parent=new_parent -> new_parent
297
+
298
+ Changes the parent of self to new_parent and returns it.*/
299
+ static VALUE
300
+ prof_call_info_set_parent(VALUE self, VALUE new_parent)
301
+ {
302
+ prof_call_info_t *result = prof_get_call_info(self);
303
+ if (new_parent == Qnil)
304
+ result->parent = NULL;
305
+ else
306
+ result->parent = prof_get_call_info(new_parent);
307
+ return prof_call_info_parent(self);
308
+ }
309
+
310
+ static int
311
+ prof_call_info_collect_children(st_data_t key, st_data_t value, st_data_t result)
312
+ {
313
+ prof_call_info_t *call_info = (prof_call_info_t *) value;
314
+ VALUE arr = (VALUE) result;
315
+ rb_ary_push(arr, prof_call_info_wrap(call_info));
316
+ return ST_CONTINUE;
317
+ }
318
+
319
+ /* call-seq:
320
+ children -> hash
321
+
322
+ Returns an array of call info objects of methods that this method
323
+ called (ie, children).*/
324
+ static VALUE
325
+ prof_call_info_children(VALUE self)
326
+ {
327
+ prof_call_info_t *call_info = prof_get_call_info(self);
328
+ if (call_info->children == Qnil)
329
+ {
330
+ call_info->children = rb_ary_new();
331
+ st_foreach(call_info->call_infos, prof_call_info_collect_children, call_info->children);
332
+ }
333
+ return call_info->children;
334
+ }
335
+
336
+ /* ======= Call Infos ========*/
337
+ prof_call_infos_t*
338
+ prof_call_infos_create()
339
+ {
340
+ prof_call_infos_t *result = ALLOC(prof_call_infos_t);
341
+ result->start = ALLOC_N(prof_call_info_t*, INITIAL_CALL_INFOS_SIZE);
342
+ result->end = result->start + INITIAL_CALL_INFOS_SIZE;
343
+ result->ptr = result->start;
344
+ result->object = Qnil;
345
+ return result;
346
+ }
347
+
348
+ void
349
+ prof_call_infos_mark(prof_call_infos_t *call_infos)
350
+ {
351
+ prof_call_info_t **call_info;
352
+
353
+ if (call_infos->object)
354
+ rb_gc_mark(call_infos->object);
355
+
356
+ for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
357
+ {
358
+ prof_call_info_mark(*call_info);
359
+ }
360
+ }
361
+
362
+ void
363
+ prof_call_infos_free(prof_call_infos_t *call_infos)
364
+ {
365
+ prof_call_info_t **call_info;
366
+
367
+ for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
368
+ {
369
+ prof_call_info_free(*call_info);
370
+ }
371
+ }
372
+
373
+ void
374
+ prof_add_call_info(prof_call_infos_t *call_infos, prof_call_info_t *call_info)
375
+ {
376
+ if (call_infos->ptr == call_infos->end)
377
+ {
378
+ size_t len = call_infos->ptr - call_infos->start;
379
+ size_t new_capacity = (call_infos->end - call_infos->start) * 2;
380
+ REALLOC_N(call_infos->start, prof_call_info_t*, new_capacity);
381
+ call_infos->ptr = call_infos->start + len;
382
+ call_infos->end = call_infos->start + new_capacity;
383
+ }
384
+ *call_infos->ptr = call_info;
385
+ call_infos->ptr++;
386
+ }
387
+
388
+ VALUE
389
+ prof_call_infos_wrap(prof_call_infos_t *call_infos)
390
+ {
391
+ if (call_infos->object == Qnil)
392
+ {
393
+ prof_call_info_t **i;
394
+ call_infos->object = rb_ary_new();
395
+ for(i=call_infos->start; i<call_infos->ptr; i++)
396
+ {
397
+ VALUE call_info = prof_call_info_wrap(*i);
398
+ rb_ary_push(call_infos->object, call_info);
399
+ }
400
+ }
401
+ return call_infos->object;
402
+ }
403
+
404
+ void rp_init_call_info()
405
+ {
406
+ /* CallInfo */
407
+ cCallInfo = rb_define_class_under(mProf, "CallInfo", rb_cObject);
408
+ rb_undef_method(CLASS_OF(cCallInfo), "new");
409
+ rb_define_method(cCallInfo, "parent", prof_call_info_parent, 0);
410
+ rb_define_method(cCallInfo, "parent=", prof_call_info_set_parent, 1);
411
+ rb_define_method(cCallInfo, "children", prof_call_info_children, 0);
412
+ rb_define_method(cCallInfo, "target", prof_call_info_target, 0);
413
+ rb_define_method(cCallInfo, "called", prof_call_info_called, 0);
414
+ rb_define_method(cCallInfo, "called=", prof_call_info_set_called, 1);
415
+ rb_define_method(cCallInfo, "total_time", prof_call_info_total_time, 0);
416
+ rb_define_method(cCallInfo, "add_total_time", prof_call_info_add_total_time, 1);
417
+ rb_define_method(cCallInfo, "self_time", prof_call_info_self_time, 0);
418
+ rb_define_method(cCallInfo, "add_self_time", prof_call_info_add_self_time, 1);
419
+ rb_define_method(cCallInfo, "wait_time", prof_call_info_wait_time, 0);
420
+ rb_define_method(cCallInfo, "add_wait_time", prof_call_info_add_wait_time, 1);
421
+
422
+ rb_define_method(cCallInfo, "recursive?", prof_call_info_recursive, 0);
423
+ rb_define_method(cCallInfo, "depth", prof_call_info_depth, 0);
424
+ rb_define_method(cCallInfo, "line", prof_call_info_line, 0);
425
+ }