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,75 +1,75 @@
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
- #ifndef __RP_METHOD_INFO__
5
- #define __RP_METHOD_INFO__
6
-
7
- #include <ruby.h>
8
-
9
- extern VALUE cMethodInfo;
10
-
11
- /* A key used to identify each method */
12
- typedef struct
13
- {
14
- VALUE klass; /* The method's class. */
15
- ID mid; /* The method id. */
16
- st_index_t key; /* Cache calculated key */
17
- } prof_method_key_t;
18
-
19
- /* Source relation bit offsets. */
20
- enum {
21
- kModuleIncludee = 0, /* Included module */
22
- kModuleSingleton, /* Singleton class of a module */
23
- kObjectSingleton /* Singleton class of an object */
24
- };
25
-
26
- /* Forward declaration, see rp_call_info.h */
27
- struct prof_call_infos_t;
28
-
29
- /* Profiling information for each method. */
30
- /* Excluded methods have no call_infos, source_klass, or source_file. */
31
- typedef struct
32
- {
33
- /* Hot */
34
-
35
- prof_method_key_t *key; /* Table key */
36
-
37
- struct prof_call_infos_t *call_infos; /* Call infos */
38
- int visits; /* Current visits on the stack */
39
-
40
- unsigned int excluded : 1; /* Exclude from profile? */
41
- unsigned int recursive : 1; /* Recursive (direct or mutual)? */
42
-
43
- /* Cold */
44
-
45
- VALUE object; /* Cached ruby object */
46
- VALUE source_klass; /* Source class */
47
- const char *source_file; /* Source file */
48
- int line; /* Line number */
49
-
50
- unsigned int resolved : 1; /* Source resolved? */
51
- unsigned int relation : 3; /* Source relation bits */
52
- } prof_method_t;
53
-
54
- void rp_init_method_info(void);
55
-
56
- void method_key(prof_method_key_t* key, VALUE klass, ID mid);
57
-
58
- st_table * method_table_create();
59
- prof_method_t * method_table_lookup(st_table *table, const prof_method_key_t* key);
60
- size_t method_table_insert(st_table *table, const prof_method_key_t *key, prof_method_t *val);
61
- void method_table_free(st_table *table);
62
-
63
- prof_method_t* prof_method_create(VALUE klass, ID mid, const char* source_file, int line);
64
- prof_method_t* prof_method_create_excluded(VALUE klass, ID mid);
65
-
66
- VALUE prof_method_wrap(prof_method_t *result);
67
- void prof_method_mark(prof_method_t *method);
68
-
69
- /* Setup infrastructure to use method keys as hash comparisons */
70
- int method_table_cmp(prof_method_key_t *key1, prof_method_key_t *key2);
71
- st_index_t method_table_hash(prof_method_key_t *key);
72
-
73
- extern struct st_hash_type type_method_hash;
74
-
75
- #endif
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_METHOD_INFO__
5
+ #define __RP_METHOD_INFO__
6
+
7
+ #include <ruby.h>
8
+
9
+ extern VALUE cMethodInfo;
10
+
11
+ /* A key used to identify each method */
12
+ typedef struct
13
+ {
14
+ VALUE klass; /* The method's class. */
15
+ ID mid; /* The method id. */
16
+ st_index_t key; /* Cache calculated key */
17
+ } prof_method_key_t;
18
+
19
+ /* Source relation bit offsets. */
20
+ enum {
21
+ kModuleIncludee = 0, /* Included module */
22
+ kModuleSingleton, /* Singleton class of a module */
23
+ kObjectSingleton /* Singleton class of an object */
24
+ };
25
+
26
+ /* Forward declaration, see rp_call_info.h */
27
+ struct prof_call_infos_t;
28
+
29
+ /* Profiling information for each method. */
30
+ /* Excluded methods have no call_infos, source_klass, or source_file. */
31
+ typedef struct
32
+ {
33
+ /* Hot */
34
+
35
+ prof_method_key_t *key; /* Table key */
36
+
37
+ struct prof_call_infos_t *call_infos; /* Call infos */
38
+ int visits; /* Current visits on the stack */
39
+
40
+ unsigned int excluded : 1; /* Exclude from profile? */
41
+ unsigned int recursive : 1; /* Recursive (direct or mutual)? */
42
+
43
+ /* Cold */
44
+
45
+ VALUE object; /* Cached ruby object */
46
+ VALUE source_klass; /* Source class */
47
+ const char *source_file; /* Source file */
48
+ int line; /* Line number */
49
+
50
+ unsigned int resolved : 1; /* Source resolved? */
51
+ unsigned int relation : 3; /* Source relation bits */
52
+ } prof_method_t;
53
+
54
+ void rp_init_method_info(void);
55
+
56
+ void method_key(prof_method_key_t* key, VALUE klass, ID mid);
57
+
58
+ st_table * method_table_create();
59
+ prof_method_t * method_table_lookup(st_table *table, const prof_method_key_t* key);
60
+ size_t method_table_insert(st_table *table, const prof_method_key_t *key, prof_method_t *val);
61
+ void method_table_free(st_table *table);
62
+
63
+ prof_method_t* prof_method_create(VALUE klass, ID mid, const char* source_file, int line);
64
+ prof_method_t* prof_method_create_excluded(VALUE klass, ID mid);
65
+
66
+ VALUE prof_method_wrap(prof_method_t *result);
67
+ void prof_method_mark(prof_method_t *method);
68
+
69
+ /* Setup infrastructure to use method keys as hash comparisons */
70
+ int method_table_cmp(prof_method_key_t *key1, prof_method_key_t *key2);
71
+ st_index_t method_table_hash(prof_method_key_t *key);
72
+
73
+ extern struct st_hash_type type_method_hash;
74
+
75
+ #endif
@@ -1,173 +1,173 @@
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_stack.h"
5
-
6
- #define INITIAL_STACK_SIZE 8
7
-
8
- void
9
- prof_frame_pause(prof_frame_t *frame, double current_measurement)
10
- {
11
- if (frame && prof_frame_is_unpaused(frame))
12
- frame->pause_time = current_measurement;
13
- }
14
-
15
- void
16
- prof_frame_unpause(prof_frame_t *frame, double current_measurement)
17
- {
18
- if (frame && prof_frame_is_paused(frame)) {
19
- frame->dead_time += (current_measurement - frame->pause_time);
20
- frame->pause_time = -1;
21
- }
22
- }
23
-
24
-
25
- /* Creates a stack of prof_frame_t to keep track
26
- of timings for active methods. */
27
- prof_stack_t *
28
- prof_stack_create()
29
- {
30
- prof_stack_t *stack = ALLOC(prof_stack_t);
31
- stack->start = ALLOC_N(prof_frame_t, INITIAL_STACK_SIZE);
32
- stack->ptr = stack->start;
33
- stack->end = stack->start + INITIAL_STACK_SIZE;
34
-
35
- return stack;
36
- }
37
-
38
- void
39
- prof_stack_free(prof_stack_t *stack)
40
- {
41
- xfree(stack->start);
42
- xfree(stack);
43
- }
44
-
45
- prof_frame_t *
46
- prof_stack_push(prof_stack_t *stack, prof_call_info_t *call_info, double measurement, int paused)
47
- {
48
- prof_frame_t *result;
49
- prof_frame_t* parent_frame;
50
- prof_method_t *method;
51
-
52
- /* Is there space on the stack? If not, double
53
- its size. */
54
- if (stack->ptr == stack->end)
55
- {
56
- size_t len = stack->ptr - stack->start;
57
- size_t new_capacity = (stack->end - stack->start) * 2;
58
- REALLOC_N(stack->start, prof_frame_t, new_capacity);
59
- /* Memory just got moved, reset pointers */
60
- stack->ptr = stack->start + len;
61
- stack->end = stack->start + new_capacity;
62
- }
63
-
64
- parent_frame = prof_stack_peek(stack);
65
-
66
- // Reserve the next available frame pointer.
67
- result = stack->ptr++;
68
-
69
- result->call_info = call_info;
70
- result->call_info->depth = (int)(stack->ptr - stack->start); // shortening of 64 bit into 32;
71
- result->passes = 0;
72
-
73
- result->start_time = measurement;
74
- result->pause_time = -1; // init as not paused.
75
- result->switch_time = 0;
76
- result->wait_time = 0;
77
- result->child_time = 0;
78
- result->dead_time = 0;
79
-
80
- method = call_info->target;
81
-
82
- /* If the method was visited previously, it's recursive. */
83
- if (method->visits > 0)
84
- {
85
- method->recursive = 1;
86
- call_info->recursive = 1;
87
- }
88
- /* Enter the method. */
89
- method->visits++;
90
-
91
- // Unpause the parent frame, if it exists.
92
- // If currently paused then:
93
- // 1) The child frame will begin paused.
94
- // 2) The parent will inherit the child's dead time.
95
- prof_frame_unpause(parent_frame, measurement);
96
-
97
- if (paused) {
98
- prof_frame_pause(result, measurement);
99
- }
100
-
101
- // Return the result
102
- return result;
103
- }
104
-
105
- prof_frame_t *
106
- prof_stack_pop(prof_stack_t *stack, double measurement)
107
- {
108
- prof_frame_t *frame;
109
- prof_frame_t *parent_frame;
110
- prof_call_info_t *call_info;
111
- prof_method_t *method;
112
-
113
- double total_time;
114
- double self_time;
115
-
116
- frame = prof_stack_peek(stack);
117
-
118
- /* Frame can be null, which means the stack is empty. This can happen if
119
- RubProf.start is called from a method that exits. And it can happen if an
120
- exception is raised in code that is being profiled and the stack unwinds
121
- (RubyProf is not notified of that by the ruby runtime. */
122
- if (!frame) {
123
- return NULL;
124
- }
125
-
126
- /* Match passes until we reach the frame itself. */
127
- if (prof_frame_is_pass(frame)) {
128
- frame->passes--;
129
- /* Additional frames can be consumed. See pop_frames(). */
130
- return frame;
131
- }
132
-
133
- /* Consume this frame. */
134
- stack->ptr--;
135
-
136
- /* Calculate the total time this method took */
137
- prof_frame_unpause(frame, measurement);
138
- total_time = measurement - frame->start_time - frame->dead_time;
139
- self_time = total_time - frame->child_time - frame->wait_time;
140
-
141
- /* Update information about the current method */
142
- call_info = frame->call_info;
143
- method = call_info->target;
144
-
145
- call_info->called++;
146
- call_info->total_time += total_time;
147
- call_info->self_time += self_time;
148
- call_info->wait_time += frame->wait_time;
149
-
150
- /* Leave the method. */
151
- method->visits--;
152
-
153
- parent_frame = prof_stack_peek(stack);
154
- if (parent_frame)
155
- {
156
- parent_frame->child_time += total_time;
157
- parent_frame->dead_time += frame->dead_time;
158
-
159
- call_info->line = parent_frame->line;
160
- }
161
-
162
- return frame;
163
- }
164
-
165
- prof_frame_t *
166
- prof_stack_pass(prof_stack_t *stack)
167
- {
168
- prof_frame_t *frame = prof_stack_peek(stack);
169
- if (frame) {
170
- frame->passes++;
171
- }
172
- return frame;
173
- }
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_stack.h"
5
+
6
+ #define INITIAL_STACK_SIZE 8
7
+
8
+ void
9
+ prof_frame_pause(prof_frame_t *frame, double current_measurement)
10
+ {
11
+ if (frame && prof_frame_is_unpaused(frame))
12
+ frame->pause_time = current_measurement;
13
+ }
14
+
15
+ void
16
+ prof_frame_unpause(prof_frame_t *frame, double current_measurement)
17
+ {
18
+ if (frame && prof_frame_is_paused(frame)) {
19
+ frame->dead_time += (current_measurement - frame->pause_time);
20
+ frame->pause_time = -1;
21
+ }
22
+ }
23
+
24
+
25
+ /* Creates a stack of prof_frame_t to keep track
26
+ of timings for active methods. */
27
+ prof_stack_t *
28
+ prof_stack_create()
29
+ {
30
+ prof_stack_t *stack = ALLOC(prof_stack_t);
31
+ stack->start = ALLOC_N(prof_frame_t, INITIAL_STACK_SIZE);
32
+ stack->ptr = stack->start;
33
+ stack->end = stack->start + INITIAL_STACK_SIZE;
34
+
35
+ return stack;
36
+ }
37
+
38
+ void
39
+ prof_stack_free(prof_stack_t *stack)
40
+ {
41
+ xfree(stack->start);
42
+ xfree(stack);
43
+ }
44
+
45
+ prof_frame_t *
46
+ prof_stack_push(prof_stack_t *stack, prof_call_info_t *call_info, double measurement, int paused)
47
+ {
48
+ prof_frame_t *result;
49
+ prof_frame_t* parent_frame;
50
+ prof_method_t *method;
51
+
52
+ /* Is there space on the stack? If not, double
53
+ its size. */
54
+ if (stack->ptr == stack->end)
55
+ {
56
+ size_t len = stack->ptr - stack->start;
57
+ size_t new_capacity = (stack->end - stack->start) * 2;
58
+ REALLOC_N(stack->start, prof_frame_t, new_capacity);
59
+ /* Memory just got moved, reset pointers */
60
+ stack->ptr = stack->start + len;
61
+ stack->end = stack->start + new_capacity;
62
+ }
63
+
64
+ parent_frame = prof_stack_peek(stack);
65
+
66
+ // Reserve the next available frame pointer.
67
+ result = stack->ptr++;
68
+
69
+ result->call_info = call_info;
70
+ result->call_info->depth = (int)(stack->ptr - stack->start); // shortening of 64 bit into 32;
71
+ result->passes = 0;
72
+
73
+ result->start_time = measurement;
74
+ result->pause_time = -1; // init as not paused.
75
+ result->switch_time = 0;
76
+ result->wait_time = 0;
77
+ result->child_time = 0;
78
+ result->dead_time = 0;
79
+
80
+ method = call_info->target;
81
+
82
+ /* If the method was visited previously, it's recursive. */
83
+ if (method->visits > 0)
84
+ {
85
+ method->recursive = 1;
86
+ call_info->recursive = 1;
87
+ }
88
+ /* Enter the method. */
89
+ method->visits++;
90
+
91
+ // Unpause the parent frame, if it exists.
92
+ // If currently paused then:
93
+ // 1) The child frame will begin paused.
94
+ // 2) The parent will inherit the child's dead time.
95
+ prof_frame_unpause(parent_frame, measurement);
96
+
97
+ if (paused) {
98
+ prof_frame_pause(result, measurement);
99
+ }
100
+
101
+ // Return the result
102
+ return result;
103
+ }
104
+
105
+ prof_frame_t *
106
+ prof_stack_pop(prof_stack_t *stack, double measurement)
107
+ {
108
+ prof_frame_t *frame;
109
+ prof_frame_t *parent_frame;
110
+ prof_call_info_t *call_info;
111
+ prof_method_t *method;
112
+
113
+ double total_time;
114
+ double self_time;
115
+
116
+ frame = prof_stack_peek(stack);
117
+
118
+ /* Frame can be null, which means the stack is empty. This can happen if
119
+ RubProf.start is called from a method that exits. And it can happen if an
120
+ exception is raised in code that is being profiled and the stack unwinds
121
+ (RubyProf is not notified of that by the ruby runtime. */
122
+ if (!frame) {
123
+ return NULL;
124
+ }
125
+
126
+ /* Match passes until we reach the frame itself. */
127
+ if (prof_frame_is_pass(frame)) {
128
+ frame->passes--;
129
+ /* Additional frames can be consumed. See pop_frames(). */
130
+ return frame;
131
+ }
132
+
133
+ /* Consume this frame. */
134
+ stack->ptr--;
135
+
136
+ /* Calculate the total time this method took */
137
+ prof_frame_unpause(frame, measurement);
138
+ total_time = measurement - frame->start_time - frame->dead_time;
139
+ self_time = total_time - frame->child_time - frame->wait_time;
140
+
141
+ /* Update information about the current method */
142
+ call_info = frame->call_info;
143
+ method = call_info->target;
144
+
145
+ call_info->called++;
146
+ call_info->total_time += total_time;
147
+ call_info->self_time += self_time;
148
+ call_info->wait_time += frame->wait_time;
149
+
150
+ /* Leave the method. */
151
+ method->visits--;
152
+
153
+ parent_frame = prof_stack_peek(stack);
154
+ if (parent_frame)
155
+ {
156
+ parent_frame->child_time += total_time;
157
+ parent_frame->dead_time += frame->dead_time;
158
+
159
+ call_info->line = parent_frame->line;
160
+ }
161
+
162
+ return frame;
163
+ }
164
+
165
+ prof_frame_t *
166
+ prof_stack_pass(prof_stack_t *stack)
167
+ {
168
+ prof_frame_t *frame = prof_stack_peek(stack);
169
+ if (frame) {
170
+ frame->passes++;
171
+ }
172
+ return frame;
173
+ }