airbnb-ruby-prof 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }