ruby-prof 0.16.2 → 1.1.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 (203) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +532 -467
  3. data/LICENSE +24 -24
  4. data/README.rdoc +5 -454
  5. data/Rakefile +110 -113
  6. data/bin/ruby-prof +380 -340
  7. data/bin/ruby-prof-check-trace +45 -45
  8. data/ext/ruby_prof/extconf.rb +36 -64
  9. data/ext/ruby_prof/rp_allocation.c +279 -0
  10. data/ext/ruby_prof/rp_allocation.h +31 -0
  11. data/ext/ruby_prof/rp_call_info.c +271 -407
  12. data/ext/ruby_prof/rp_call_info.h +35 -48
  13. data/ext/ruby_prof/rp_measure_allocations.c +52 -76
  14. data/ext/ruby_prof/rp_measure_memory.c +42 -77
  15. data/ext/ruby_prof/rp_measure_process_time.c +67 -71
  16. data/ext/ruby_prof/rp_measure_wall_time.c +62 -45
  17. data/ext/ruby_prof/rp_measurement.c +230 -0
  18. data/ext/ruby_prof/rp_measurement.h +50 -0
  19. data/ext/ruby_prof/rp_method.c +630 -411
  20. data/ext/ruby_prof/rp_method.h +70 -52
  21. data/ext/ruby_prof/rp_profile.c +895 -0
  22. data/ext/ruby_prof/rp_profile.h +37 -0
  23. data/ext/ruby_prof/rp_stack.c +196 -128
  24. data/ext/ruby_prof/rp_stack.h +56 -51
  25. data/ext/ruby_prof/rp_thread.c +337 -273
  26. data/ext/ruby_prof/rp_thread.h +36 -27
  27. data/ext/ruby_prof/ruby_prof.c +48 -671
  28. data/ext/ruby_prof/ruby_prof.h +17 -56
  29. data/ext/ruby_prof/vc/ruby_prof.sln +20 -21
  30. data/ext/ruby_prof/vc/{ruby_prof_20.vcxproj → ruby_prof.vcxproj} +38 -5
  31. data/lib/ruby-prof.rb +52 -58
  32. data/lib/ruby-prof/assets/call_stack_printer.html.erb +713 -0
  33. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  34. data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
  35. data/lib/ruby-prof/call_info.rb +57 -126
  36. data/lib/ruby-prof/call_info_visitor.rb +38 -40
  37. data/lib/ruby-prof/compatibility.rb +109 -178
  38. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  39. data/lib/ruby-prof/measurement.rb +14 -0
  40. data/lib/ruby-prof/method_info.rb +90 -129
  41. data/lib/ruby-prof/printers/abstract_printer.rb +127 -85
  42. data/lib/ruby-prof/printers/call_info_printer.rb +51 -41
  43. data/lib/ruby-prof/printers/call_stack_printer.rb +182 -260
  44. data/lib/ruby-prof/printers/call_tree_printer.rb +151 -130
  45. data/lib/ruby-prof/printers/dot_printer.rb +132 -132
  46. data/lib/ruby-prof/printers/flat_printer.rb +52 -70
  47. data/lib/ruby-prof/printers/graph_html_printer.rb +63 -244
  48. data/lib/ruby-prof/printers/graph_printer.rb +114 -116
  49. data/lib/ruby-prof/printers/multi_printer.rb +127 -58
  50. data/lib/ruby-prof/profile.rb +33 -55
  51. data/lib/ruby-prof/rack.rb +171 -95
  52. data/lib/ruby-prof/task.rb +147 -147
  53. data/lib/ruby-prof/thread.rb +35 -41
  54. data/lib/ruby-prof/version.rb +3 -3
  55. data/lib/unprof.rb +10 -10
  56. data/ruby-prof.gemspec +58 -57
  57. data/test/abstract_printer_test.rb +26 -0
  58. data/test/alias_test.rb +129 -0
  59. data/test/basic_test.rb +129 -128
  60. data/test/call_info_visitor_test.rb +31 -31
  61. data/test/duplicate_names_test.rb +32 -32
  62. data/test/dynamic_method_test.rb +53 -55
  63. data/test/enumerable_test.rb +21 -21
  64. data/test/exceptions_test.rb +24 -16
  65. data/test/exclude_methods_test.rb +146 -0
  66. data/test/exclude_threads_test.rb +53 -53
  67. data/test/fiber_test.rb +73 -79
  68. data/test/gc_test.rb +96 -0
  69. data/test/line_number_test.rb +161 -71
  70. data/test/marshal_test.rb +119 -0
  71. data/test/measure_allocations.rb +30 -0
  72. data/test/measure_allocations_test.rb +385 -26
  73. data/test/measure_allocations_trace_test.rb +385 -0
  74. data/test/measure_memory_trace_test.rb +756 -0
  75. data/test/measure_process_time_test.rb +849 -63
  76. data/test/measure_times.rb +54 -0
  77. data/test/measure_wall_time_test.rb +459 -255
  78. data/test/multi_printer_test.rb +71 -83
  79. data/test/no_method_class_test.rb +15 -15
  80. data/test/parser_timings.rb +24 -0
  81. data/test/pause_resume_test.rb +166 -166
  82. data/test/prime.rb +56 -54
  83. data/test/printer_call_stack_test.rb +28 -0
  84. data/test/printer_call_tree_test.rb +31 -0
  85. data/test/printer_flat_test.rb +68 -0
  86. data/test/printer_graph_html_test.rb +60 -0
  87. data/test/printer_graph_test.rb +41 -0
  88. data/test/printers_test.rb +141 -255
  89. data/test/printing_recursive_graph_test.rb +81 -127
  90. data/test/rack_test.rb +157 -93
  91. data/test/recursive_test.rb +210 -215
  92. data/test/singleton_test.rb +38 -38
  93. data/test/stack_printer_test.rb +64 -78
  94. data/test/start_stop_test.rb +109 -112
  95. data/test/test_helper.rb +24 -264
  96. data/test/thread_test.rb +144 -187
  97. data/test/unique_call_path_test.rb +190 -202
  98. data/test/yarv_test.rb +56 -55
  99. metadata +34 -114
  100. data/doc/LICENSE.html +0 -114
  101. data/doc/README_rdoc.html +0 -603
  102. data/doc/Rack.html +0 -95
  103. data/doc/Rack/RubyProf.html +0 -226
  104. data/doc/RubyProf.html +0 -962
  105. data/doc/RubyProf/AbstractPrinter.html +0 -546
  106. data/doc/RubyProf/AggregateCallInfo.html +0 -551
  107. data/doc/RubyProf/CallInfo.html +0 -639
  108. data/doc/RubyProf/CallInfoPrinter.html +0 -120
  109. data/doc/RubyProf/CallInfoVisitor.html +0 -198
  110. data/doc/RubyProf/CallStackPrinter.html +0 -1121
  111. data/doc/RubyProf/CallTreePrinter.html +0 -641
  112. data/doc/RubyProf/Cmd.html +0 -631
  113. data/doc/RubyProf/DotPrinter.html +0 -257
  114. data/doc/RubyProf/FlatPrinter.html +0 -163
  115. data/doc/RubyProf/FlatPrinterWithLineNumbers.html +0 -208
  116. data/doc/RubyProf/GraphHtmlPrinter.html +0 -552
  117. data/doc/RubyProf/GraphPrinter.html +0 -139
  118. data/doc/RubyProf/MethodInfo.html +0 -745
  119. data/doc/RubyProf/MultiPrinter.html +0 -360
  120. data/doc/RubyProf/Profile.html +0 -763
  121. data/doc/RubyProf/ProfileTask.html +0 -490
  122. data/doc/RubyProf/Thread.html +0 -310
  123. data/doc/created.rid +0 -31
  124. data/doc/css/fonts.css +0 -167
  125. data/doc/css/rdoc.css +0 -590
  126. data/doc/examples/flat_txt.html +0 -138
  127. data/doc/examples/graph_html.html +0 -909
  128. data/doc/examples/graph_txt.html +0 -247
  129. data/doc/fonts/Lato-Light.ttf +0 -0
  130. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  131. data/doc/fonts/Lato-Regular.ttf +0 -0
  132. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  133. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  134. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  135. data/doc/images/add.png +0 -0
  136. data/doc/images/arrow_up.png +0 -0
  137. data/doc/images/brick.png +0 -0
  138. data/doc/images/brick_link.png +0 -0
  139. data/doc/images/bug.png +0 -0
  140. data/doc/images/bullet_black.png +0 -0
  141. data/doc/images/bullet_toggle_minus.png +0 -0
  142. data/doc/images/bullet_toggle_plus.png +0 -0
  143. data/doc/images/date.png +0 -0
  144. data/doc/images/delete.png +0 -0
  145. data/doc/images/find.png +0 -0
  146. data/doc/images/loadingAnimation.gif +0 -0
  147. data/doc/images/macFFBgHack.png +0 -0
  148. data/doc/images/package.png +0 -0
  149. data/doc/images/page_green.png +0 -0
  150. data/doc/images/page_white_text.png +0 -0
  151. data/doc/images/page_white_width.png +0 -0
  152. data/doc/images/plugin.png +0 -0
  153. data/doc/images/ruby.png +0 -0
  154. data/doc/images/tag_blue.png +0 -0
  155. data/doc/images/tag_green.png +0 -0
  156. data/doc/images/transparent.png +0 -0
  157. data/doc/images/wrench.png +0 -0
  158. data/doc/images/wrench_orange.png +0 -0
  159. data/doc/images/zoom.png +0 -0
  160. data/doc/index.html +0 -626
  161. data/doc/js/darkfish.js +0 -161
  162. data/doc/js/jquery.js +0 -4
  163. data/doc/js/navigation.js +0 -142
  164. data/doc/js/navigation.js.gz +0 -0
  165. data/doc/js/search.js +0 -109
  166. data/doc/js/search_index.js +0 -1
  167. data/doc/js/search_index.js.gz +0 -0
  168. data/doc/js/searcher.js +0 -228
  169. data/doc/js/searcher.js.gz +0 -0
  170. data/doc/table_of_contents.html +0 -942
  171. data/examples/cachegrind.out.1 +0 -114
  172. data/examples/cachegrind.out.1.32313213 +0 -114
  173. data/examples/flat.txt +0 -50
  174. data/examples/graph.dot +0 -84
  175. data/examples/graph.html +0 -823
  176. data/examples/graph.txt +0 -139
  177. data/examples/multi.flat.txt +0 -23
  178. data/examples/multi.graph.html +0 -760
  179. data/examples/multi.grind.dat +0 -114
  180. data/examples/multi.stack.html +0 -547
  181. data/examples/stack.html +0 -547
  182. data/ext/ruby_prof/rp_measure.c +0 -40
  183. data/ext/ruby_prof/rp_measure.h +0 -45
  184. data/ext/ruby_prof/rp_measure_cpu_time.c +0 -136
  185. data/ext/ruby_prof/rp_measure_gc_runs.c +0 -73
  186. data/ext/ruby_prof/rp_measure_gc_time.c +0 -60
  187. data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +0 -108
  188. data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +0 -110
  189. data/lib/ruby-prof/aggregate_call_info.rb +0 -76
  190. data/lib/ruby-prof/assets/call_stack_printer.css.html +0 -117
  191. data/lib/ruby-prof/assets/call_stack_printer.js.html +0 -385
  192. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -64
  193. data/test/aggregate_test.rb +0 -136
  194. data/test/block_test.rb +0 -74
  195. data/test/call_info_test.rb +0 -78
  196. data/test/issue137_test.rb +0 -63
  197. data/test/measure_cpu_time_test.rb +0 -213
  198. data/test/measure_gc_runs_test.rb +0 -32
  199. data/test/measure_gc_time_test.rb +0 -36
  200. data/test/measure_memory_test.rb +0 -33
  201. data/test/method_elimination_test.rb +0 -84
  202. data/test/module_test.rb +0 -45
  203. data/test/stack_test.rb +0 -138
@@ -0,0 +1,31 @@
1
+ /* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
2
+ Please see the LICENSE file for copyright and distribution information */
3
+
4
+ #ifndef _RP_ALLOCATION_
5
+ #define _RP_ALLOCATION_
6
+
7
+ #include "ruby_prof.h"
8
+ #include "rp_method.h"
9
+
10
+ typedef struct
11
+ {
12
+ st_data_t key; /* Key in hash table */
13
+ unsigned int klass_flags; /* Information about the type of class */
14
+ VALUE klass; /* Klass that was created */
15
+ VALUE klass_name; /* Name of the class that was created */
16
+ VALUE source_file; /* Line number where allocation happens */
17
+ int source_line; /* Line number where allocation happens */
18
+ int count; /* Number of allocations */
19
+ size_t memory; /* Amount of allocated memory */
20
+ VALUE object; /* Cache to wrapped object */
21
+ } prof_allocation_t;
22
+
23
+ void rp_init_allocation(void);
24
+ void prof_allocation_free(prof_allocation_t* allocation);
25
+ void prof_allocation_mark(void *data);
26
+ VALUE prof_allocation_wrap(prof_allocation_t* allocation);
27
+ prof_allocation_t* prof_allocation_get(VALUE self);
28
+ prof_allocation_t* prof_allocate_increment(prof_method_t *method, rb_trace_arg_t *trace_arg);
29
+
30
+
31
+ #endif //_RP_ALLOCATION_
@@ -1,407 +1,271 @@
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->called = 0;
27
- result->total_time = 0;
28
- result->self_time = 0;
29
- result->wait_time = 0;
30
- result->line = 0;
31
- return result;
32
- }
33
- static void
34
- prof_call_info_ruby_gc_free(prof_call_info_t *call_info)
35
- {
36
- /* Has this thread object been accessed by Ruby? If
37
- yes clean it up so to avoid a segmentation fault. */
38
- if (call_info->object != Qnil)
39
- {
40
- RDATA(call_info->object)->data = NULL;
41
- RDATA(call_info->object)->dfree = NULL;
42
- RDATA(call_info->object)->dmark = NULL;
43
- }
44
- call_info->object = Qnil;
45
- }
46
-
47
- static void
48
- prof_call_info_free(prof_call_info_t *call_info)
49
- {
50
- prof_call_info_ruby_gc_free(call_info);
51
- st_free_table(call_info->call_infos);
52
- xfree(call_info);
53
- }
54
-
55
- static void
56
- prof_call_info_mark(prof_call_info_t *call_info)
57
- {
58
- if (call_info->object)
59
- rb_gc_mark(call_info->object);
60
-
61
- if (call_info->children)
62
- rb_gc_mark(call_info->children);
63
-
64
- /* We don't mark the call info child table since that will be done
65
- via the appropriate method */
66
- }
67
-
68
- VALUE
69
- prof_call_info_wrap(prof_call_info_t *call_info)
70
- {
71
- if (call_info->object == Qnil)
72
- {
73
- call_info->object = Data_Wrap_Struct(cCallInfo, prof_call_info_mark, prof_call_info_ruby_gc_free, call_info);
74
- }
75
- return call_info->object;
76
- }
77
-
78
- static prof_call_info_t *
79
- prof_get_call_info(VALUE self)
80
- {
81
- /* Can't use Data_Get_Struct because that triggers the event hook
82
- ending up in endless recursion. */
83
- prof_call_info_t* result = DATA_PTR(self);
84
-
85
- if (!result)
86
- rb_raise(rb_eRuntimeError, "This RubyProf::CallInfo instance has already been freed, likely because its profile has been freed.");
87
-
88
- return result;
89
- }
90
-
91
- /* ======= Call Info Table ========*/
92
- st_table *
93
- call_info_table_create()
94
- {
95
- return st_init_table(&type_method_hash);
96
- }
97
-
98
- size_t
99
- call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val)
100
- {
101
- return st_insert(table, (st_data_t) key, (st_data_t) val);
102
- }
103
-
104
- prof_call_info_t *
105
- call_info_table_lookup(st_table *table, const prof_method_key_t *key)
106
- {
107
- st_data_t val;
108
- if (st_lookup(table, (st_data_t) key, &val))
109
- {
110
- return (prof_call_info_t *) val;
111
- }
112
- else
113
- {
114
- return NULL;
115
- }
116
- }
117
-
118
-
119
- /* ======= RubyProf::CallInfo ========*/
120
-
121
- /* Document-class: RubyProf::CallInfo
122
- RubyProf::CallInfo is a helper class used by RubyProf::MethodInfo
123
- to keep track of which child methods were called and how long
124
- they took to execute. */
125
-
126
-
127
- /* call-seq:
128
- called -> MethodInfo
129
-
130
- Returns the target method. */
131
- static VALUE
132
- prof_call_info_target(VALUE self)
133
- {
134
- /* Target is a pointer to a method_info - so we have to be careful
135
- about the GC. We will wrap the method_info but provide no
136
- free method so the underlying object is not freed twice! */
137
-
138
- prof_call_info_t *result = prof_get_call_info(self);
139
- return prof_method_wrap(result->target);
140
- }
141
-
142
- /* call-seq:
143
- called -> int
144
-
145
- Returns the total amount of times this method was called. */
146
- static VALUE
147
- prof_call_info_called(VALUE self)
148
- {
149
- prof_call_info_t *result = prof_get_call_info(self);
150
- return INT2NUM(result->called);
151
- }
152
-
153
- /* call-seq:
154
- called=n -> n
155
-
156
- Sets the call count to n. */
157
- static VALUE
158
- prof_call_info_set_called(VALUE self, VALUE called)
159
- {
160
- prof_call_info_t *result = prof_get_call_info(self);
161
- result->called = NUM2INT(called);
162
- return called;
163
- }
164
-
165
- /* call-seq:
166
- depth -> int
167
-
168
- returns the depth of this call info in the call graph */
169
- static VALUE
170
- prof_call_info_depth(VALUE self)
171
- {
172
- prof_call_info_t *result = prof_get_call_info(self);
173
- return rb_int_new(result->depth);
174
- }
175
-
176
- /* call-seq:
177
- line_no -> int
178
-
179
- returns the line number of the method */
180
- static VALUE
181
- prof_call_info_line(VALUE self)
182
- {
183
- prof_call_info_t *result = prof_get_call_info(self);
184
- return rb_int_new(result->line);
185
- }
186
-
187
- /* call-seq:
188
- total_time -> float
189
-
190
- Returns the total amount of time spent in this method and its children. */
191
- static VALUE
192
- prof_call_info_total_time(VALUE self)
193
- {
194
- prof_call_info_t *result = prof_get_call_info(self);
195
- return rb_float_new(result->total_time);
196
- }
197
-
198
- /* call-seq:
199
- add_total_time(call_info) -> nil
200
-
201
- adds total time time from call_info to self. */
202
- static VALUE
203
- prof_call_info_add_total_time(VALUE self, VALUE other)
204
- {
205
- prof_call_info_t *result = prof_get_call_info(self);
206
- prof_call_info_t *other_info = prof_get_call_info(other);
207
-
208
- result->total_time += other_info->total_time;
209
- return Qnil;
210
- }
211
-
212
- /* call-seq:
213
- self_time -> float
214
-
215
- Returns the total amount of time spent in this method. */
216
- static VALUE
217
- prof_call_info_self_time(VALUE self)
218
- {
219
- prof_call_info_t *result = prof_get_call_info(self);
220
-
221
- return rb_float_new(result->self_time);
222
- }
223
-
224
- /* call-seq:
225
- add_self_time(call_info) -> nil
226
-
227
- adds self time from call_info to self. */
228
- static VALUE
229
- prof_call_info_add_self_time(VALUE self, VALUE other)
230
- {
231
- prof_call_info_t *result = prof_get_call_info(self);
232
- prof_call_info_t *other_info = prof_get_call_info(other);
233
-
234
- result->self_time += other_info->self_time;
235
- return Qnil;
236
- }
237
-
238
- /* call-seq:
239
- wait_time -> float
240
-
241
- Returns the total amount of time this method waited for other threads. */
242
- static VALUE
243
- prof_call_info_wait_time(VALUE self)
244
- {
245
- prof_call_info_t *result = prof_get_call_info(self);
246
-
247
- return rb_float_new(result->wait_time);
248
- }
249
-
250
- /* call-seq:
251
- add_wait_time(call_info) -> nil
252
-
253
- adds wait time from call_info to self. */
254
-
255
- static VALUE
256
- prof_call_info_add_wait_time(VALUE self, VALUE other)
257
- {
258
- prof_call_info_t *result = prof_get_call_info(self);
259
- prof_call_info_t *other_info = prof_get_call_info(other);
260
-
261
- result->wait_time += other_info->wait_time;
262
- return Qnil;
263
- }
264
-
265
- /* call-seq:
266
- parent -> call_info
267
-
268
- Returns the call_infos parent call_info object (the method that called this method).*/
269
- static VALUE
270
- prof_call_info_parent(VALUE self)
271
- {
272
- prof_call_info_t *result = prof_get_call_info(self);
273
- if (result->parent)
274
- return prof_call_info_wrap(result->parent);
275
- else
276
- return Qnil;
277
- }
278
-
279
- /* call-seq:
280
- parent=new_parent -> new_parent
281
-
282
- Changes the parent of self to new_parent and returns it.*/
283
- static VALUE
284
- prof_call_info_set_parent(VALUE self, VALUE new_parent)
285
- {
286
- prof_call_info_t *result = prof_get_call_info(self);
287
- if (new_parent == Qnil)
288
- result->parent = NULL;
289
- else
290
- result->parent = prof_get_call_info(new_parent);
291
- return prof_call_info_parent(self);
292
- }
293
-
294
- static int
295
- prof_call_info_collect_children(st_data_t key, st_data_t value, st_data_t result)
296
- {
297
- prof_call_info_t *call_info = (prof_call_info_t *) value;
298
- VALUE arr = (VALUE) result;
299
- rb_ary_push(arr, prof_call_info_wrap(call_info));
300
- return ST_CONTINUE;
301
- }
302
-
303
- /* call-seq:
304
- children -> hash
305
-
306
- Returns an array of call info objects of methods that this method
307
- called (ie, children).*/
308
- static VALUE
309
- prof_call_info_children(VALUE self)
310
- {
311
- prof_call_info_t *call_info = prof_get_call_info(self);
312
- if (call_info->children == Qnil)
313
- {
314
- call_info->children = rb_ary_new();
315
- st_foreach(call_info->call_infos, prof_call_info_collect_children, call_info->children);
316
- }
317
- return call_info->children;
318
- }
319
-
320
- /* ======= Call Infos ========*/
321
- prof_call_infos_t*
322
- prof_call_infos_create()
323
- {
324
- prof_call_infos_t *result = ALLOC(prof_call_infos_t);
325
- result->start = ALLOC_N(prof_call_info_t*, INITIAL_CALL_INFOS_SIZE);
326
- result->end = result->start + INITIAL_CALL_INFOS_SIZE;
327
- result->ptr = result->start;
328
- result->object = Qnil;
329
- return result;
330
- }
331
-
332
- void
333
- prof_call_infos_mark(prof_call_infos_t *call_infos)
334
- {
335
- prof_call_info_t **call_info;
336
-
337
- if (call_infos->object)
338
- rb_gc_mark(call_infos->object);
339
-
340
- for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
341
- {
342
- prof_call_info_mark(*call_info);
343
- }
344
- }
345
-
346
- void
347
- prof_call_infos_free(prof_call_infos_t *call_infos)
348
- {
349
- prof_call_info_t **call_info;
350
-
351
- for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
352
- {
353
- prof_call_info_free(*call_info);
354
- }
355
- }
356
-
357
- void
358
- prof_add_call_info(prof_call_infos_t *call_infos, prof_call_info_t *call_info)
359
- {
360
- if (call_infos->ptr == call_infos->end)
361
- {
362
- size_t len = call_infos->ptr - call_infos->start;
363
- size_t new_capacity = (call_infos->end - call_infos->start) * 2;
364
- REALLOC_N(call_infos->start, prof_call_info_t*, new_capacity);
365
- call_infos->ptr = call_infos->start + len;
366
- call_infos->end = call_infos->start + new_capacity;
367
- }
368
- *call_infos->ptr = call_info;
369
- call_infos->ptr++;
370
- }
371
-
372
- VALUE
373
- prof_call_infos_wrap(prof_call_infos_t *call_infos)
374
- {
375
- if (call_infos->object == Qnil)
376
- {
377
- prof_call_info_t **i;
378
- call_infos->object = rb_ary_new();
379
- for(i=call_infos->start; i<call_infos->ptr; i++)
380
- {
381
- VALUE call_info = prof_call_info_wrap(*i);
382
- rb_ary_push(call_infos->object, call_info);
383
- }
384
- }
385
- return call_infos->object;
386
- }
387
-
388
- void rp_init_call_info()
389
- {
390
- /* CallInfo */
391
- cCallInfo = rb_define_class_under(mProf, "CallInfo", rb_cObject);
392
- rb_undef_method(CLASS_OF(cCallInfo), "new");
393
- rb_define_method(cCallInfo, "parent", prof_call_info_parent, 0);
394
- rb_define_method(cCallInfo, "parent=", prof_call_info_set_parent, 1);
395
- rb_define_method(cCallInfo, "children", prof_call_info_children, 0);
396
- rb_define_method(cCallInfo, "target", prof_call_info_target, 0);
397
- rb_define_method(cCallInfo, "called", prof_call_info_called, 0);
398
- rb_define_method(cCallInfo, "called=", prof_call_info_set_called, 1);
399
- rb_define_method(cCallInfo, "total_time", prof_call_info_total_time, 0);
400
- rb_define_method(cCallInfo, "add_total_time", prof_call_info_add_total_time, 1);
401
- rb_define_method(cCallInfo, "self_time", prof_call_info_self_time, 0);
402
- rb_define_method(cCallInfo, "add_self_time", prof_call_info_add_self_time, 1);
403
- rb_define_method(cCallInfo, "wait_time", prof_call_info_wait_time, 0);
404
- rb_define_method(cCallInfo, "add_wait_time", prof_call_info_add_wait_time, 1);
405
- rb_define_method(cCallInfo, "depth", prof_call_info_depth, 0);
406
- rb_define_method(cCallInfo, "line", prof_call_info_line, 0);
407
- }
1
+ /* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
2
+ Please see the LICENSE file for copyright and distribution information */
3
+
4
+ #include "rp_call_info.h"
5
+
6
+ #define INITIAL_CALL_INFOS_SIZE 2
7
+
8
+ VALUE cRpCallnfo;
9
+
10
+ /* ======= prof_call_info_t ========*/
11
+ prof_call_info_t *
12
+ prof_call_info_create(prof_method_t *method, prof_method_t *parent, VALUE source_file, int source_line)
13
+ {
14
+ prof_call_info_t *result = ALLOC(prof_call_info_t);
15
+ result->method = method;
16
+ result->parent = parent;
17
+ result->object = Qnil;
18
+ result->measurement = prof_measurement_create();
19
+
20
+ result->visits = 0;
21
+
22
+ result->depth = 0;
23
+ result->source_line = source_line;
24
+ result->source_file = source_file;
25
+
26
+ return result;
27
+ }
28
+
29
+ static void
30
+ prof_call_info_ruby_gc_free(void *data)
31
+ {
32
+ prof_call_info_t *call_info = (prof_call_info_t*)data;
33
+
34
+ /* Has this call info object been accessed by Ruby? If
35
+ yes clean it up so to avoid a segmentation fault. */
36
+ if (call_info->object != Qnil)
37
+ {
38
+ RDATA(call_info->object)->dmark = NULL;
39
+ RDATA(call_info->object)->dfree = NULL;
40
+ RDATA(call_info->object)->data = NULL;
41
+ call_info->object = Qnil;
42
+ }
43
+ }
44
+
45
+ void
46
+ prof_call_info_free(prof_call_info_t *call_info)
47
+ {
48
+ prof_measurement_free(call_info->measurement);
49
+ prof_call_info_ruby_gc_free(call_info);
50
+ xfree(call_info);
51
+ }
52
+
53
+ size_t
54
+ prof_call_info_size(const void *data)
55
+ {
56
+ return sizeof(prof_call_info_t);
57
+ }
58
+
59
+ void
60
+ prof_call_info_mark(void *data)
61
+ {
62
+ prof_call_info_t *call_info = (prof_call_info_t*)data;
63
+
64
+ if (call_info->source_file != Qnil)
65
+ rb_gc_mark(call_info->source_file);
66
+
67
+ if (call_info->object != Qnil)
68
+ rb_gc_mark(call_info->object);
69
+
70
+ if (call_info->method && call_info->method->object != Qnil)
71
+ rb_gc_mark(call_info->method->object);
72
+
73
+ if (call_info->parent && call_info->parent->object != Qnil)
74
+ rb_gc_mark(call_info->parent->object);
75
+
76
+ prof_measurement_mark(call_info->measurement);
77
+ }
78
+
79
+ VALUE
80
+ prof_call_info_wrap(prof_call_info_t *call_info)
81
+ {
82
+ if (call_info->object == Qnil)
83
+ {
84
+ call_info->object = Data_Wrap_Struct(cRpCallnfo, prof_call_info_mark, prof_call_info_ruby_gc_free, call_info);
85
+ }
86
+ return call_info->object;
87
+ }
88
+
89
+ static VALUE
90
+ prof_call_info_allocate(VALUE klass)
91
+ {
92
+ prof_call_info_t* call_info = prof_call_info_create(NULL, NULL, Qnil, 0);
93
+ call_info->object = prof_call_info_wrap(call_info);
94
+ return call_info->object;
95
+ }
96
+
97
+ prof_call_info_t *
98
+ prof_get_call_info(VALUE self)
99
+ {
100
+ /* Can't use Data_Get_Struct because that triggers the event hook
101
+ ending up in endless recursion. */
102
+ prof_call_info_t* result = DATA_PTR(self);
103
+
104
+ if (!result)
105
+ rb_raise(rb_eRuntimeError, "This RubyProf::CallInfo instance has already been freed, likely because its profile has been freed.");
106
+
107
+ return result;
108
+ }
109
+
110
+ /* ======= Call Info Table ========*/
111
+ st_table *
112
+ call_info_table_create()
113
+ {
114
+ return st_init_numtable();
115
+ }
116
+
117
+ size_t
118
+ call_info_table_insert(st_table *table, st_data_t key, prof_call_info_t *val)
119
+ {
120
+ return st_insert(table, (st_data_t) key, (st_data_t) val);
121
+ }
122
+
123
+ prof_call_info_t *
124
+ call_info_table_lookup(st_table *table, st_data_t key)
125
+ {
126
+ st_data_t val;
127
+ if (st_lookup(table, (st_data_t) key, &val))
128
+ {
129
+ return (prof_call_info_t *) val;
130
+ }
131
+ else
132
+ {
133
+ return NULL;
134
+ }
135
+ }
136
+
137
+ /* ======= RubyProf::CallInfo ========*/
138
+
139
+ /* call-seq:
140
+ parent -> call_info
141
+
142
+ Returns the call_infos parent call_info object (the method that called this method).*/
143
+ static VALUE
144
+ prof_call_info_parent(VALUE self)
145
+ {
146
+ prof_call_info_t* call_info = prof_get_call_info(self);
147
+ if (call_info->parent)
148
+ return prof_method_wrap(call_info->parent);
149
+ else
150
+ return Qnil;
151
+ }
152
+
153
+ /* call-seq:
154
+ called -> MethodInfo
155
+
156
+ Returns the target method. */
157
+ static VALUE
158
+ prof_call_info_target(VALUE self)
159
+ {
160
+ prof_call_info_t *call_info = prof_get_call_info(self);
161
+ return prof_method_wrap(call_info->method);
162
+ }
163
+
164
+ /* call-seq:
165
+ called -> Measurement
166
+
167
+ Returns the measurement associated with this call_info. */
168
+ static VALUE
169
+ prof_call_info_measurement(VALUE self)
170
+ {
171
+ prof_call_info_t* call_info = prof_get_call_info(self);
172
+ return prof_measurement_wrap(call_info->measurement);
173
+ }
174
+
175
+ /* call-seq:
176
+ depth -> int
177
+
178
+ returns the depth of this call info in the call graph */
179
+ static VALUE
180
+ prof_call_info_depth(VALUE self)
181
+ {
182
+ prof_call_info_t *result = prof_get_call_info(self);
183
+ return rb_int_new(result->depth);
184
+ }
185
+
186
+ /* call-seq:
187
+ source_file => string
188
+
189
+ return the source file of the method
190
+ */
191
+ static VALUE
192
+ prof_call_info_source_file(VALUE self)
193
+ {
194
+ prof_call_info_t* result = prof_get_call_info(self);
195
+ return result->source_file;
196
+ }
197
+
198
+ /* call-seq:
199
+ line_no -> int
200
+
201
+ returns the line number of the method */
202
+ static VALUE
203
+ prof_call_info_line(VALUE self)
204
+ {
205
+ prof_call_info_t *result = prof_get_call_info(self);
206
+ return INT2FIX(result->source_line);
207
+ }
208
+
209
+ /* :nodoc: */
210
+ static VALUE
211
+ prof_call_info_dump(VALUE self)
212
+ {
213
+ prof_call_info_t* call_info_data = prof_get_call_info(self);
214
+ VALUE result = rb_hash_new();
215
+
216
+ rb_hash_aset(result, ID2SYM(rb_intern("measurement")), prof_measurement_wrap(call_info_data->measurement));
217
+
218
+ rb_hash_aset(result, ID2SYM(rb_intern("depth")), INT2FIX(call_info_data->depth));
219
+ rb_hash_aset(result, ID2SYM(rb_intern("source_file")), call_info_data->source_file);
220
+ rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(call_info_data->source_line));
221
+
222
+ rb_hash_aset(result, ID2SYM(rb_intern("parent")), prof_call_info_parent(self));
223
+ rb_hash_aset(result, ID2SYM(rb_intern("target")), prof_call_info_target(self));
224
+
225
+ return result;
226
+ }
227
+
228
+ /* :nodoc: */
229
+ static VALUE
230
+ prof_call_info_load(VALUE self, VALUE data)
231
+ {
232
+ VALUE target = Qnil;
233
+ VALUE parent = Qnil;
234
+ prof_call_info_t* call_info = prof_get_call_info(self);
235
+ call_info->object = self;
236
+
237
+ VALUE measurement = rb_hash_aref(data, ID2SYM(rb_intern("measurement")));
238
+ call_info->measurement = prof_get_measurement(measurement);
239
+
240
+ call_info->depth = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("depth"))));
241
+ call_info->source_file = rb_hash_aref(data, ID2SYM(rb_intern("source_file")));
242
+ call_info->source_line = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("source_line"))));
243
+
244
+ parent = rb_hash_aref(data, ID2SYM(rb_intern("parent")));
245
+ if (parent != Qnil)
246
+ call_info->parent = prof_method_get(parent);
247
+
248
+ target = rb_hash_aref(data, ID2SYM(rb_intern("target")));
249
+ call_info->method = prof_method_get(target);
250
+
251
+ return data;
252
+ }
253
+
254
+ void rp_init_call_info()
255
+ {
256
+ /* CallInfo */
257
+ cRpCallnfo = rb_define_class_under(mProf, "CallInfo", rb_cData);
258
+ rb_undef_method(CLASS_OF(cRpCallnfo), "new");
259
+ rb_define_alloc_func(cRpCallnfo, prof_call_info_allocate);
260
+
261
+ rb_define_method(cRpCallnfo, "parent", prof_call_info_parent, 0);
262
+ rb_define_method(cRpCallnfo, "target", prof_call_info_target, 0);
263
+ rb_define_method(cRpCallnfo, "measurement", prof_call_info_measurement, 0);
264
+
265
+ rb_define_method(cRpCallnfo, "depth", prof_call_info_depth, 0);
266
+ rb_define_method(cRpCallnfo, "source_file", prof_call_info_source_file, 0);
267
+ rb_define_method(cRpCallnfo, "line", prof_call_info_line, 0);
268
+
269
+ rb_define_method(cRpCallnfo, "_dump_data", prof_call_info_dump, 0);
270
+ rb_define_method(cRpCallnfo, "_load_data", prof_call_info_load, 1);
271
+ }