airbnb-ruby-prof 0.0.1

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 (116) hide show
  1. data/CHANGES +483 -0
  2. data/LICENSE +25 -0
  3. data/README.rdoc +426 -0
  4. data/Rakefile +51 -0
  5. data/bin/ruby-prof +279 -0
  6. data/bin/ruby-prof-check-trace +45 -0
  7. data/examples/flat.txt +50 -0
  8. data/examples/graph.dot +84 -0
  9. data/examples/graph.html +823 -0
  10. data/examples/graph.txt +139 -0
  11. data/examples/multi.flat.txt +23 -0
  12. data/examples/multi.graph.html +760 -0
  13. data/examples/multi.grind.dat +114 -0
  14. data/examples/multi.stack.html +547 -0
  15. data/examples/stack.html +547 -0
  16. data/ext/ruby_prof/extconf.rb +67 -0
  17. data/ext/ruby_prof/rp_call_info.c +374 -0
  18. data/ext/ruby_prof/rp_call_info.h +59 -0
  19. data/ext/ruby_prof/rp_fast_call_tree_printer.c +247 -0
  20. data/ext/ruby_prof/rp_fast_call_tree_printer.h +10 -0
  21. data/ext/ruby_prof/rp_measure.c +71 -0
  22. data/ext/ruby_prof/rp_measure.h +56 -0
  23. data/ext/ruby_prof/rp_measure_allocations.c +74 -0
  24. data/ext/ruby_prof/rp_measure_cpu_time.c +134 -0
  25. data/ext/ruby_prof/rp_measure_gc_runs.c +71 -0
  26. data/ext/ruby_prof/rp_measure_gc_time.c +58 -0
  27. data/ext/ruby_prof/rp_measure_memory.c +75 -0
  28. data/ext/ruby_prof/rp_measure_process_time.c +69 -0
  29. data/ext/ruby_prof/rp_measure_wall_time.c +43 -0
  30. data/ext/ruby_prof/rp_method.c +717 -0
  31. data/ext/ruby_prof/rp_method.h +79 -0
  32. data/ext/ruby_prof/rp_stack.c +221 -0
  33. data/ext/ruby_prof/rp_stack.h +81 -0
  34. data/ext/ruby_prof/rp_thread.c +312 -0
  35. data/ext/ruby_prof/rp_thread.h +36 -0
  36. data/ext/ruby_prof/ruby_prof.c +800 -0
  37. data/ext/ruby_prof/ruby_prof.h +64 -0
  38. data/ext/ruby_prof/vc/ruby_prof.sln +32 -0
  39. data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +108 -0
  40. data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +110 -0
  41. data/ext/ruby_prof/vc/ruby_prof_20.vcxproj +110 -0
  42. data/lib/ruby-prof.rb +63 -0
  43. data/lib/ruby-prof/aggregate_call_info.rb +76 -0
  44. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  45. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  46. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  47. data/lib/ruby-prof/assets/flame_graph_printer.lib.css.html +149 -0
  48. data/lib/ruby-prof/assets/flame_graph_printer.lib.js.html +707 -0
  49. data/lib/ruby-prof/assets/flame_graph_printer.page.js.html +56 -0
  50. data/lib/ruby-prof/assets/flame_graph_printer.tmpl.html.erb +39 -0
  51. data/lib/ruby-prof/call_info.rb +111 -0
  52. data/lib/ruby-prof/call_info_visitor.rb +40 -0
  53. data/lib/ruby-prof/compatibility.rb +186 -0
  54. data/lib/ruby-prof/method_info.rb +109 -0
  55. data/lib/ruby-prof/printers/abstract_printer.rb +85 -0
  56. data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
  57. data/lib/ruby-prof/printers/call_stack_printer.rb +260 -0
  58. data/lib/ruby-prof/printers/call_tree_printer.rb +130 -0
  59. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  60. data/lib/ruby-prof/printers/fast_call_tree_printer.rb +87 -0
  61. data/lib/ruby-prof/printers/flame_graph_html_printer.rb +59 -0
  62. data/lib/ruby-prof/printers/flame_graph_json_printer.rb +157 -0
  63. data/lib/ruby-prof/printers/flat_printer.rb +70 -0
  64. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +64 -0
  65. data/lib/ruby-prof/printers/graph_html_printer.rb +244 -0
  66. data/lib/ruby-prof/printers/graph_printer.rb +116 -0
  67. data/lib/ruby-prof/printers/multi_printer.rb +58 -0
  68. data/lib/ruby-prof/profile.rb +22 -0
  69. data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
  70. data/lib/ruby-prof/rack.rb +95 -0
  71. data/lib/ruby-prof/task.rb +147 -0
  72. data/lib/ruby-prof/thread.rb +35 -0
  73. data/lib/ruby-prof/version.rb +4 -0
  74. data/lib/ruby-prof/walker.rb +95 -0
  75. data/lib/unprof.rb +10 -0
  76. data/ruby-prof.gemspec +56 -0
  77. data/test/aggregate_test.rb +136 -0
  78. data/test/basic_test.rb +128 -0
  79. data/test/block_test.rb +74 -0
  80. data/test/call_info_test.rb +78 -0
  81. data/test/call_info_visitor_test.rb +31 -0
  82. data/test/duplicate_names_test.rb +32 -0
  83. data/test/dynamic_method_test.rb +55 -0
  84. data/test/enumerable_test.rb +21 -0
  85. data/test/exceptions_test.rb +16 -0
  86. data/test/exclude_methods_test.rb +146 -0
  87. data/test/exclude_threads_test.rb +53 -0
  88. data/test/fiber_test.rb +79 -0
  89. data/test/issue137_test.rb +63 -0
  90. data/test/line_number_test.rb +71 -0
  91. data/test/measure_allocations_test.rb +26 -0
  92. data/test/measure_cpu_time_test.rb +213 -0
  93. data/test/measure_gc_runs_test.rb +32 -0
  94. data/test/measure_gc_time_test.rb +36 -0
  95. data/test/measure_memory_test.rb +33 -0
  96. data/test/measure_process_time_test.rb +63 -0
  97. data/test/measure_wall_time_test.rb +255 -0
  98. data/test/module_test.rb +45 -0
  99. data/test/multi_measure_test.rb +38 -0
  100. data/test/multi_printer_test.rb +83 -0
  101. data/test/no_method_class_test.rb +15 -0
  102. data/test/pause_resume_test.rb +166 -0
  103. data/test/prime.rb +54 -0
  104. data/test/printers_test.rb +255 -0
  105. data/test/printing_recursive_graph_test.rb +127 -0
  106. data/test/rack_test.rb +93 -0
  107. data/test/recursive_test.rb +212 -0
  108. data/test/singleton_test.rb +38 -0
  109. data/test/stack_printer_test.rb +65 -0
  110. data/test/stack_test.rb +138 -0
  111. data/test/start_stop_test.rb +112 -0
  112. data/test/test_helper.rb +264 -0
  113. data/test/thread_test.rb +187 -0
  114. data/test/unique_call_path_test.rb +202 -0
  115. data/test/yarv_test.rb +55 -0
  116. metadata +211 -0
@@ -0,0 +1,247 @@
1
+ #include "ruby_prof.h"
2
+ #include "math.h"
3
+
4
+ VALUE cFastCallTreePrinter;
5
+ static ID id_addstr;
6
+
7
+ /* Utility struct to mirror the require ivars in the ruby class.
8
+
9
+ output is a ruby IO object
10
+
11
+ value_scale is the conversion factor used to scale the result for rounding.
12
+ This is set based on the measure mode. */
13
+ typedef struct call_tree_printer_vars
14
+ {
15
+ VALUE output;
16
+ size_t len;
17
+ double value_scales[];
18
+ } call_tree_printer_vars;
19
+
20
+ static call_tree_printer_vars *
21
+ call_tree_printer_vars_allocate(size_t len)
22
+ {
23
+ call_tree_printer_vars *result =
24
+ (call_tree_printer_vars*) ruby_xmalloc(
25
+ sizeof(call_tree_printer_vars) + len * sizeof(double));
26
+ result->len = len;
27
+ return result;
28
+ }
29
+
30
+ /* Converts the recorded value to a fixed point number based on value scale */
31
+ static long int
32
+ convert(double value, double value_scale)
33
+ {
34
+ return lround(value * value_scale);
35
+ }
36
+
37
+ static VALUE
38
+ addstr(VALUE io, VALUE str)
39
+ {
40
+ return rb_funcall(io, id_addstr, 1, str);
41
+ }
42
+
43
+ static void
44
+ print_header(
45
+ call_tree_printer_vars *vars,
46
+ prof_method_t *method,
47
+ char *name)
48
+ {
49
+ /* Format is file and method name followed by line and self time */
50
+ addstr(
51
+ vars->output,
52
+ rb_sprintf(
53
+ "fl=%s\nfn=%s\n%d",
54
+ prof_method_t_source_file(method),
55
+ name,
56
+ method->line));
57
+ }
58
+
59
+ /* Returns the index of the callee in the call_infos list. */
60
+ static int
61
+ call_info_index(prof_call_infos_t *call_infos, prof_call_info_t *callee)
62
+ {
63
+ prof_call_info_t **i;
64
+ for (i = call_infos->start; i < call_infos->ptr; i++) {
65
+ if ((*i) == callee) {
66
+ return i - call_infos->start;
67
+ }
68
+ }
69
+
70
+ return -1;
71
+ }
72
+
73
+ static void
74
+ print_child(call_tree_printer_vars *vars, prof_call_info_t *callee)
75
+ {
76
+ prof_method_t *target = callee->target;
77
+ VALUE name = prof_method_t_calltree_name(target);
78
+
79
+ if (target->recursive) {
80
+ int index = call_info_index(target->call_infos, callee);
81
+ name = rb_sprintf("%s [%d]", RSTRING_PTR(name), index);
82
+ }
83
+
84
+ addstr(
85
+ vars->output,
86
+ rb_sprintf(
87
+ "cfl=%s\ncfn=%s\ncalls=%d %d\n%d",
88
+ prof_method_t_source_file(target),
89
+ RSTRING_PTR(name),
90
+ callee->called,
91
+ callee->line,
92
+ callee->line));
93
+
94
+ for(size_t i = 0; i < callee->measures_len; i++) {
95
+ addstr(
96
+ vars->output,
97
+ rb_sprintf(
98
+ " %ld",
99
+ convert(callee->measure_values[i].total, vars->value_scales[i])));
100
+ }
101
+ addstr(vars->output, rb_str_new2("\n"));
102
+
103
+ RB_GC_GUARD(name);
104
+ }
105
+
106
+ /* Function to be called by st_foreach to print each child call info */
107
+ static int
108
+ print_child_iter(st_data_t key, st_data_t value, st_data_t vars)
109
+ {
110
+ print_child((call_tree_printer_vars *) vars, (prof_call_info_t *) value);
111
+ return ST_CONTINUE;
112
+ }
113
+
114
+ static void
115
+ print_simple_method(call_tree_printer_vars *vars, prof_method_t *method)
116
+ {
117
+ VALUE calltree_name = prof_method_t_calltree_name(method);
118
+ size_t measures_len = (*method->call_infos->start)->measures_len;
119
+
120
+ print_header(vars, method, RSTRING_PTR(calltree_name));
121
+ for(size_t j = 0; j < measures_len; j++) {
122
+ addstr(vars->output,
123
+ rb_sprintf(" %ld", convert(prof_method_t_self_time(method, j), vars->value_scales[j])));
124
+ }
125
+ addstr(vars->output, rb_str_new2("\n"));
126
+
127
+ prof_call_info_t **i;
128
+ for(i = method->call_infos->start; i < method->call_infos->ptr; i++) {
129
+ st_foreach((*i)->call_infos, print_child_iter, (uintptr_t) vars);
130
+ }
131
+
132
+ RB_GC_GUARD(calltree_name);
133
+ }
134
+
135
+ static void
136
+ print_recursive_method(call_tree_printer_vars *vars, prof_method_t *method)
137
+ {
138
+ VALUE calltree_name = prof_method_t_calltree_name(method);
139
+
140
+ prof_call_info_t **i;
141
+ for(i = method->call_infos->start; i < method->call_infos->ptr; i++) {
142
+ int index = i - method->call_infos->start;
143
+ VALUE name = rb_sprintf("%s [%d]", RSTRING_PTR(calltree_name), index);
144
+
145
+ print_header(vars, method, RSTRING_PTR(name));
146
+ for(size_t j = 0; j < (*i)->measures_len; j++) {
147
+ addstr(vars->output,
148
+ rb_sprintf(" %ld", convert((*i)->measure_values[j].self, vars->value_scales[j])));
149
+ }
150
+ addstr(vars->output, rb_str_new2("\n"));
151
+
152
+ st_foreach((*i)->call_infos, print_child_iter, (uintptr_t) vars);
153
+
154
+ RB_GC_GUARD(name);
155
+ }
156
+
157
+ RB_GC_GUARD(calltree_name);
158
+ }
159
+
160
+ static int
161
+ print_method(call_tree_printer_vars *vars, prof_method_t *method)
162
+ {
163
+ if(!method->excluded) {
164
+ if (method->recursive) {
165
+ print_recursive_method(vars, method);
166
+ } else {
167
+ print_simple_method(vars, method);
168
+ }
169
+
170
+ addstr(vars->output, rb_str_new2("\n"));
171
+ }
172
+
173
+ return ST_CONTINUE;
174
+ }
175
+
176
+ /* Iterator to handle reversing an st_table of methods into a provided array */
177
+ static int
178
+ reverse_methods(st_data_t key, st_data_t value, st_data_t arg)
179
+ {
180
+ prof_method_t ***methods = (prof_method_t ***) arg;
181
+
182
+ prof_method_t *method = (prof_method_t *) value;
183
+
184
+ *methods = *methods - 1;
185
+ **methods = method;
186
+
187
+ return ST_CONTINUE;
188
+ }
189
+
190
+ static void
191
+ print_methods_in_reverse(call_tree_printer_vars *vars, st_table *method_table)
192
+ {
193
+ st_index_t num_entries = method_table->num_entries;
194
+
195
+ prof_method_t **reversed = ALLOC_N(prof_method_t*, num_entries);
196
+ prof_method_t **end = reversed + num_entries;
197
+
198
+ prof_method_t **iterator = end;
199
+
200
+ st_foreach(method_table, reverse_methods, (uintptr_t) &iterator);
201
+
202
+ prof_method_t **i;
203
+ for(i = reversed; i < end; i++) {
204
+ print_method(vars, *i);
205
+ }
206
+
207
+ xfree(reversed);
208
+ }
209
+
210
+
211
+ /* call-seq:
212
+ print_thread(thread) -> nil
213
+
214
+ Prints to @output the call tree of a thread
215
+ */
216
+ VALUE
217
+ prof_fast_call_tree_printer_print_thread(VALUE self, VALUE thread) {
218
+ thread_data_t *thread_data = prof_get_thread(thread);
219
+
220
+ VALUE output = rb_iv_get(self, "@output");
221
+ VALUE value_scales_val = rb_iv_get(self, "@value_scales");
222
+
223
+ Check_Type(value_scales_val, T_ARRAY);
224
+ size_t value_scales_len = RARRAY_LEN(value_scales_val);
225
+
226
+ call_tree_printer_vars *vars = call_tree_printer_vars_allocate(value_scales_len);
227
+ vars->output = output;
228
+ for(size_t i = 0; i < value_scales_len; i++) {
229
+ vars->value_scales[i] = NUM2DBL(rb_ary_entry(value_scales_val, i));
230
+ }
231
+
232
+ print_methods_in_reverse(vars, thread_data->method_table);
233
+
234
+ xfree(vars);
235
+
236
+ return Qnil;
237
+ }
238
+
239
+ void rp_init_fast_call_tree_printer()
240
+ {
241
+ id_addstr = rb_intern("<<");
242
+
243
+ cFastCallTreePrinter = rb_define_class_under(mProf,
244
+ "FastCallTreePrinter", rb_cObject);
245
+ rb_define_method(cFastCallTreePrinter, "print_thread",
246
+ prof_fast_call_tree_printer_print_thread, 1);
247
+ }
@@ -0,0 +1,10 @@
1
+ #ifndef __RP_FAST_CALL_TREE_PRINTER_H__
2
+ #define __RP_FAST_CALL_TREE_PRINTER_H__
3
+
4
+ #include <ruby.h>
5
+
6
+ extern VALUE cFastCallTreePrinter;
7
+
8
+ void rp_init_fast_call_tree_printer(void);
9
+
10
+ #endif
@@ -0,0 +1,71 @@
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
+ VALUE mMeasure;
7
+
8
+ prof_measurer_t*
9
+ prof_measurer_allocate(size_t len)
10
+ {
11
+ prof_measurer_t* result =
12
+ (prof_measurer_t*) ruby_xmalloc(
13
+ sizeof(prof_measurer_t) + len * sizeof(get_measurement));
14
+ result->len = len;
15
+ return result;
16
+ }
17
+
18
+ prof_measurer_t* prof_get_measurer(prof_measure_mode_t* measures, size_t len)
19
+ {
20
+ prof_measurer_t* measurer = prof_measurer_allocate(len);
21
+ measurer->measure_modes = measures;
22
+
23
+ for (size_t i = 0; i < len; i++) {
24
+ switch (measures[i]) {
25
+ case MEASURE_WALL_TIME:
26
+ measurer->measures[i] = prof_measurer_wall_time();
27
+ break;
28
+ case MEASURE_PROCESS_TIME:
29
+ measurer->measures[i] = prof_measurer_process_time();
30
+ break;
31
+ case MEASURE_CPU_TIME:
32
+ measurer->measures[i] = prof_measurer_cpu_time();
33
+ break;
34
+ case MEASURE_ALLOCATIONS:
35
+ measurer->measures[i] = prof_measurer_allocations();
36
+ break;
37
+ case MEASURE_MEMORY:
38
+ measurer->measures[i] = prof_measurer_memory();
39
+ break;
40
+ case MEASURE_GC_TIME:
41
+ measurer->measures[i] = prof_measurer_gc_time();
42
+ break;
43
+ case MEASURE_GC_RUNS:
44
+ measurer->measures[i] = prof_measurer_gc_runs();
45
+ break;
46
+ default:
47
+ rb_raise(rb_eArgError, "Unknown measure mode: %d", measures[i]);
48
+ }
49
+ }
50
+
51
+ return measurer;
52
+ };
53
+
54
+ void prof_measurer_take_measurements(prof_measurer_t* measurer, prof_measurements_t* dest)
55
+ {
56
+ for (size_t i = 0; i < measurer->len; i++) {
57
+ dest->values[i] = measurer->measures[i]();
58
+ }
59
+ }
60
+
61
+ void rp_init_measure()
62
+ {
63
+ mMeasure = rb_define_module_under(mProf, "Measure");
64
+ rp_init_measure_wall_time();
65
+ rp_init_measure_cpu_time();
66
+ rp_init_measure_process_time();
67
+ rp_init_measure_allocations();
68
+ rp_init_measure_memory();
69
+ rp_init_measure_gc_time();
70
+ rp_init_measure_gc_runs();
71
+ }
@@ -0,0 +1,56 @@
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_MEASUREMENT_H__
5
+ #define __RP_MEASUREMENT_H__
6
+
7
+ extern VALUE mMeasure;
8
+
9
+ typedef struct
10
+ {
11
+ size_t len;
12
+ double values[];
13
+ } prof_measurements_t;
14
+
15
+ typedef double (*get_measurement)();
16
+
17
+ typedef enum
18
+ {
19
+ MEASURE_WALL_TIME,
20
+ MEASURE_PROCESS_TIME,
21
+ MEASURE_CPU_TIME,
22
+ MEASURE_ALLOCATIONS,
23
+ MEASURE_MEMORY,
24
+ MEASURE_GC_TIME,
25
+ MEASURE_GC_RUNS,
26
+ } prof_measure_mode_t;
27
+
28
+ typedef struct
29
+ {
30
+ size_t len;
31
+ prof_measure_mode_t* measure_modes;
32
+ get_measurement measures[];
33
+ } prof_measurer_t;
34
+
35
+
36
+ prof_measurer_t* prof_get_measurer(prof_measure_mode_t* measures, size_t len);
37
+ get_measurement prof_measurer_allocations();
38
+ get_measurement prof_measurer_cpu_time();
39
+ get_measurement prof_measurer_gc_runs();
40
+ get_measurement prof_measurer_gc_time();
41
+ get_measurement prof_measurer_memory();
42
+ get_measurement prof_measurer_process_time();
43
+ get_measurement prof_measurer_wall_time();
44
+
45
+ void prof_measurer_take_measurements(prof_measurer_t* measurer, prof_measurements_t* dest);
46
+
47
+ void rp_init_measure();
48
+ void rp_init_measure_allocations();
49
+ void rp_init_measure_cpu_time();
50
+ void rp_init_measure_gc_runs();
51
+ void rp_init_measure_gc_time();
52
+ void rp_init_measure_memory();
53
+ void rp_init_measure_process_time();
54
+ void rp_init_measure_wall_time();
55
+
56
+ #endif //__RP_MEASUREMENT_H__
@@ -0,0 +1,74 @@
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
+ /* :nodoc: */
5
+
6
+ #include "ruby_prof.h"
7
+
8
+ static VALUE cMeasureAllocations;
9
+
10
+ #if defined(HAVE_RB_OS_ALLOCATED_OBJECTS)
11
+ unsigned LONG_LONG rb_os_allocated_objects();
12
+ #endif
13
+
14
+ #if defined(HAVE_RB_GC_STAT)
15
+ size_t rb_gc_stat(VALUE key);
16
+
17
+ #if RUBY_PROF_RUBY_VERSION >= 20200
18
+ #define TOTAL_ALLOCATED_OBJECTS_STRING "total_allocated_objects"
19
+ #else
20
+ #define TOTAL_ALLOCATED_OBJECTS_STRING "total_allocated_object"
21
+ #endif
22
+
23
+ #endif
24
+
25
+ static double
26
+ measure_allocations()
27
+ {
28
+ #if defined(HAVE_RB_OS_ALLOCATED_OBJECTS)
29
+ #define MEASURE_ALLOCATIONS_ENABLED Qtrue
30
+ return rb_os_allocated_objects();
31
+
32
+ #elif defined(HAVE_RB_GC_STAT) && RUBY_PROF_RUBY_VERSION >= 20100
33
+ #define MEASURE_ALLOCATIONS_ENABLED Qtrue
34
+ static VALUE total_alloc_symbol = 0;
35
+ if (!total_alloc_symbol) {
36
+ total_alloc_symbol = ID2SYM(rb_intern_const(TOTAL_ALLOCATED_OBJECTS_STRING));
37
+ }
38
+ return rb_gc_stat(total_alloc_symbol);
39
+
40
+ #else
41
+ #define MEASURE_ALLOCATIONS_ENABLED Qfalse
42
+ return 0;
43
+ #endif
44
+ }
45
+
46
+
47
+ get_measurement prof_measurer_allocations()
48
+ {
49
+ return measure_allocations;
50
+ }
51
+
52
+ /* call-seq:
53
+ measure -> int
54
+
55
+ Returns the number of Ruby object allocations. */
56
+
57
+ static VALUE
58
+ prof_measure_allocations(VALUE self)
59
+ {
60
+ #if defined(HAVE_LONG_LONG)
61
+ return ULL2NUM(measure_allocations());
62
+ #else
63
+ return ULONG2NUM(measure_allocations());
64
+ #endif
65
+ }
66
+
67
+ void rp_init_measure_allocations()
68
+ {
69
+ rb_define_const(mProf, "ALLOCATIONS", INT2NUM(MEASURE_ALLOCATIONS));
70
+ rb_define_const(mProf, "ALLOCATIONS_ENABLED", MEASURE_ALLOCATIONS_ENABLED);
71
+
72
+ cMeasureAllocations = rb_define_class_under(mMeasure, "Allocations", rb_cObject);
73
+ rb_define_singleton_method(cMeasureAllocations, "measure", prof_measure_allocations, 0);
74
+ }