ruby-prof 1.4.3 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +59 -9
  3. data/{README.rdoc → README.md} +2 -2
  4. data/Rakefile +4 -4
  5. data/bin/ruby-prof +100 -87
  6. data/ext/ruby_prof/rp_allocation.c +140 -85
  7. data/ext/ruby_prof/rp_allocation.h +8 -6
  8. data/ext/ruby_prof/rp_call_tree.c +502 -369
  9. data/ext/ruby_prof/rp_call_tree.h +47 -43
  10. data/ext/ruby_prof/rp_call_trees.c +16 -8
  11. data/ext/ruby_prof/rp_measure_allocations.c +10 -13
  12. data/ext/ruby_prof/rp_measure_memory.c +8 -4
  13. data/ext/ruby_prof/rp_measure_process_time.c +7 -6
  14. data/ext/ruby_prof/rp_measurement.c +147 -20
  15. data/ext/ruby_prof/rp_measurement.h +4 -1
  16. data/ext/ruby_prof/rp_method.c +142 -83
  17. data/ext/ruby_prof/rp_method.h +63 -62
  18. data/ext/ruby_prof/rp_profile.c +933 -900
  19. data/ext/ruby_prof/rp_profile.h +1 -0
  20. data/ext/ruby_prof/rp_thread.c +433 -362
  21. data/ext/ruby_prof/rp_thread.h +39 -39
  22. data/ext/ruby_prof/ruby_prof.c +0 -2
  23. data/ext/ruby_prof/ruby_prof.h +8 -0
  24. data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -8
  25. data/lib/ruby-prof/assets/call_stack_printer.html.erb +2 -1
  26. data/lib/ruby-prof/compatibility.rb +14 -0
  27. data/lib/ruby-prof/method_info.rb +8 -1
  28. data/lib/ruby-prof/printers/abstract_printer.rb +2 -1
  29. data/lib/ruby-prof/printers/call_tree_printer.rb +4 -10
  30. data/lib/ruby-prof/printers/graph_html_printer.rb +1 -1
  31. data/lib/ruby-prof/printers/multi_printer.rb +17 -17
  32. data/lib/ruby-prof/profile.rb +70 -37
  33. data/lib/ruby-prof/rack.rb +31 -21
  34. data/lib/ruby-prof/version.rb +1 -1
  35. data/lib/ruby-prof.rb +1 -1
  36. data/ruby-prof.gemspec +2 -3
  37. data/test/abstract_printer_test.rb +1 -0
  38. data/test/alias_test.rb +97 -106
  39. data/test/call_tree_builder.rb +126 -0
  40. data/test/call_tree_test.rb +94 -0
  41. data/test/call_tree_visitor_test.rb +1 -6
  42. data/test/call_trees_test.rb +6 -6
  43. data/test/{basic_test.rb → compatibility_test.rb} +8 -2
  44. data/test/duplicate_names_test.rb +5 -5
  45. data/test/dynamic_method_test.rb +24 -15
  46. data/test/enumerable_test.rb +1 -1
  47. data/test/exceptions_test.rb +2 -2
  48. data/test/exclude_methods_test.rb +3 -8
  49. data/test/exclude_threads_test.rb +4 -9
  50. data/test/fiber_test.rb +74 -8
  51. data/test/gc_test.rb +11 -9
  52. data/test/inverse_call_tree_test.rb +33 -34
  53. data/test/line_number_test.rb +37 -61
  54. data/test/marshal_test.rb +16 -3
  55. data/test/measure_allocations.rb +1 -5
  56. data/test/measure_allocations_test.rb +642 -357
  57. data/test/{measure_memory_trace_test.rb → measure_memory_test.rb} +180 -616
  58. data/test/measure_process_time_test.rb +1566 -741
  59. data/test/measure_wall_time_test.rb +179 -193
  60. data/test/measurement_test.rb +82 -0
  61. data/test/merge_test.rb +146 -0
  62. data/test/method_info_test.rb +95 -0
  63. data/test/multi_printer_test.rb +0 -5
  64. data/test/no_method_class_test.rb +1 -1
  65. data/test/pause_resume_test.rb +12 -16
  66. data/test/printer_call_stack_test.rb +2 -2
  67. data/test/printer_call_tree_test.rb +4 -4
  68. data/test/printer_flat_test.rb +1 -1
  69. data/test/printer_graph_html_test.rb +2 -2
  70. data/test/printer_graph_test.rb +2 -2
  71. data/test/printers_test.rb +14 -20
  72. data/test/printing_recursive_graph_test.rb +2 -2
  73. data/test/profile_test.rb +85 -0
  74. data/test/recursive_test.rb +374 -155
  75. data/test/scheduler.rb +363 -0
  76. data/test/singleton_test.rb +1 -1
  77. data/test/stack_printer_test.rb +5 -8
  78. data/test/start_stop_test.rb +11 -14
  79. data/test/test_helper.rb +11 -8
  80. data/test/thread_test.rb +106 -15
  81. data/test/unique_call_path_test.rb +28 -12
  82. data/test/yarv_test.rb +11 -7
  83. metadata +17 -29
  84. data/ext/ruby_prof/rp_aggregate_call_tree.c +0 -59
  85. data/ext/ruby_prof/rp_aggregate_call_tree.h +0 -13
  86. data/test/measure_allocations_trace_test.rb +0 -375
  87. data/test/temp.rb +0 -20
@@ -2,32 +2,11 @@
2
2
  Please see the LICENSE file for copyright and distribution information */
3
3
 
4
4
  #include "rp_allocation.h"
5
+ #include "rp_method.h"
5
6
 
6
7
  VALUE cRpAllocation;
7
8
 
8
- prof_allocation_t* allocations_table_lookup(st_table* table, st_data_t key)
9
- {
10
- prof_allocation_t* result = NULL;
11
- st_data_t value;
12
- if (rb_st_lookup(table, key, &value))
13
- {
14
- result = (prof_allocation_t*)value;
15
- }
16
-
17
- return result;
18
- }
19
-
20
- void allocations_table_insert(st_table* table, st_data_t key, prof_allocation_t* allocation)
21
- {
22
- rb_st_insert(table, (st_data_t)key, (st_data_t)allocation);
23
- }
24
-
25
- st_data_t allocations_key(VALUE klass, int source_line)
26
- {
27
- return (klass << 4) + source_line;
28
- }
29
-
30
- /* ====== prof_allocation_t ====== */
9
+ // ------ prof_allocation_t ------
31
10
  prof_allocation_t* prof_allocation_create(void)
32
11
  {
33
12
  prof_allocation_t* result = ALLOC(prof_allocation_t);
@@ -43,48 +22,17 @@ prof_allocation_t* prof_allocation_create(void)
43
22
  return result;
44
23
  }
45
24
 
46
- prof_allocation_t* prof_get_allocation(VALUE self)
25
+ prof_allocation_t* prof_allocation_get(VALUE self)
47
26
  {
48
27
  /* Can't use Data_Get_Struct because that triggers the event hook
49
28
  ending up in endless recursion. */
50
29
  prof_allocation_t* result = RTYPEDDATA_DATA(self);
51
-
52
30
  if (!result)
53
31
  rb_raise(rb_eRuntimeError, "This RubyProf::Allocation instance has already been freed, likely because its profile has been freed.");
54
32
 
55
33
  return result;
56
34
  }
57
35
 
58
- prof_allocation_t* prof_allocate_increment(prof_method_t* method, rb_trace_arg_t* trace_arg)
59
- {
60
- VALUE object = rb_tracearg_object(trace_arg);
61
- if (BUILTIN_TYPE(object) == T_IMEMO)
62
- return NULL;
63
-
64
- VALUE klass = rb_obj_class(object);
65
-
66
- int source_line = FIX2INT(rb_tracearg_lineno(trace_arg));
67
- st_data_t key = allocations_key(klass, source_line);
68
-
69
- prof_allocation_t* allocation = allocations_table_lookup(method->allocations_table, key);
70
- if (!allocation)
71
- {
72
- allocation = prof_allocation_create();
73
- allocation->source_line = source_line;
74
- allocation->source_file = rb_tracearg_path(trace_arg);
75
- allocation->klass_flags = 0;
76
- allocation->klass = resolve_klass(klass, &allocation->klass_flags);
77
-
78
- allocation->key = key;
79
- allocations_table_insert(method->allocations_table, key, allocation);
80
- }
81
-
82
- allocation->count++;
83
- allocation->memory += rb_obj_memsize_of(object);
84
-
85
- return allocation;
86
- }
87
-
88
36
  static void prof_allocation_ruby_gc_free(void* data)
89
37
  {
90
38
  if (data)
@@ -118,30 +66,39 @@ void prof_allocation_mark(void* data)
118
66
 
119
67
  prof_allocation_t* allocation = (prof_allocation_t*)data;
120
68
  if (allocation->object != Qnil)
121
- rb_gc_mark(allocation->object);
69
+ rb_gc_mark_movable(allocation->object);
122
70
 
123
71
  if (allocation->klass != Qnil)
124
- rb_gc_mark(allocation->klass);
72
+ rb_gc_mark_movable(allocation->klass);
125
73
 
126
74
  if (allocation->klass_name != Qnil)
127
- rb_gc_mark(allocation->klass_name);
75
+ rb_gc_mark_movable(allocation->klass_name);
128
76
 
129
77
  if (allocation->source_file != Qnil)
130
78
  rb_gc_mark(allocation->source_file);
131
79
  }
132
80
 
133
- static const rb_data_type_t allocation_type =
81
+ void prof_allocation_compact(void* data)
134
82
  {
135
- .wrap_struct_name = "Allocation",
136
- .function =
137
- {
138
- .dmark = prof_allocation_mark,
139
- .dfree = prof_allocation_ruby_gc_free,
140
- .dsize = prof_allocation_size,
141
- },
142
- .data = NULL,
143
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
144
- };
83
+ prof_allocation_t* allocation = (prof_allocation_t*)data;
84
+ allocation->object = rb_gc_location(allocation->object);
85
+ allocation->klass = rb_gc_location(allocation->klass);
86
+ allocation->klass_name = rb_gc_location(allocation->klass_name);
87
+ }
88
+
89
+ static const rb_data_type_t allocation_type =
90
+ {
91
+ .wrap_struct_name = "Allocation",
92
+ .function =
93
+ {
94
+ .dmark = prof_allocation_mark,
95
+ .dfree = prof_allocation_ruby_gc_free,
96
+ .dsize = prof_allocation_size,
97
+ .dcompact = prof_allocation_compact
98
+ },
99
+ .data = NULL,
100
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
101
+ };
145
102
 
146
103
  VALUE prof_allocation_wrap(prof_allocation_t* allocation)
147
104
  {
@@ -152,24 +109,122 @@ VALUE prof_allocation_wrap(prof_allocation_t* allocation)
152
109
  return allocation->object;
153
110
  }
154
111
 
155
- static VALUE prof_allocation_allocate(VALUE klass)
112
+ /* ====== Allocation Table ====== */
113
+ st_table* prof_allocations_create()
156
114
  {
157
- prof_allocation_t* allocation = prof_allocation_create();
158
- allocation->object = prof_allocation_wrap(allocation);
159
- return allocation->object;
115
+ return rb_st_init_numtable();
160
116
  }
161
117
 
162
- prof_allocation_t* prof_allocation_get(VALUE self)
118
+ static int allocations_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
163
119
  {
164
- /* Can't use Data_Get_Struct because that triggers the event hook
165
- ending up in endless recursion. */
166
- prof_allocation_t* result = RTYPEDDATA_DATA(self);
167
- if (!result)
168
- rb_raise(rb_eRuntimeError, "This RubyProf::Allocation instance has already been freed, likely because its profile has been freed.");
120
+ prof_allocation_free((prof_allocation_t*)value);
121
+ return ST_CONTINUE;
122
+ }
123
+
124
+ st_data_t allocations_key(VALUE klass, int source_line)
125
+ {
126
+ return (klass << 4) + source_line;
127
+ }
128
+
129
+ static int prof_allocations_collect(st_data_t key, st_data_t value, st_data_t result)
130
+ {
131
+ prof_allocation_t* allocation = (prof_allocation_t*)value;
132
+ VALUE arr = (VALUE)result;
133
+ rb_ary_push(arr, prof_allocation_wrap(allocation));
134
+ return ST_CONTINUE;
135
+ }
136
+
137
+ static int prof_allocations_mark_each(st_data_t key, st_data_t value, st_data_t data)
138
+ {
139
+ prof_allocation_t* allocation = (prof_allocation_t*)value;
140
+ prof_allocation_mark(allocation);
141
+ return ST_CONTINUE;
142
+ }
143
+
144
+ void prof_allocations_mark(st_table* allocations_table)
145
+ {
146
+ rb_st_foreach(allocations_table, prof_allocations_mark_each, 0);
147
+ }
148
+
149
+ void prof_allocations_free(st_table* table)
150
+ {
151
+ rb_st_foreach(table, allocations_table_free_iterator, 0);
152
+ rb_st_free_table(table);
153
+ }
154
+
155
+ prof_allocation_t* allocations_table_lookup(st_table* table, st_data_t key)
156
+ {
157
+ prof_allocation_t* result = NULL;
158
+ st_data_t value;
159
+ if (rb_st_lookup(table, key, &value))
160
+ {
161
+ result = (prof_allocation_t*)value;
162
+ }
169
163
 
170
164
  return result;
171
165
  }
172
166
 
167
+ void allocations_table_insert(st_table* table, st_data_t key, prof_allocation_t* allocation)
168
+ {
169
+ rb_st_insert(table, (st_data_t)key, (st_data_t)allocation);
170
+ }
171
+
172
+ prof_allocation_t* prof_allocate_increment(st_table* allocations_table, rb_trace_arg_t* trace_arg)
173
+ {
174
+ VALUE object = rb_tracearg_object(trace_arg);
175
+ if (BUILTIN_TYPE(object) == T_IMEMO)
176
+ return NULL;
177
+
178
+ VALUE klass = rb_obj_class(object);
179
+
180
+ int source_line = FIX2INT(rb_tracearg_lineno(trace_arg));
181
+ st_data_t key = allocations_key(klass, source_line);
182
+
183
+ prof_allocation_t* allocation = allocations_table_lookup(allocations_table, key);
184
+ if (!allocation)
185
+ {
186
+ allocation = prof_allocation_create();
187
+ allocation->source_line = source_line;
188
+ allocation->source_file = rb_tracearg_path(trace_arg);
189
+ allocation->klass_flags = 0;
190
+ allocation->klass = resolve_klass(klass, &allocation->klass_flags);
191
+
192
+ allocation->key = key;
193
+ allocations_table_insert(allocations_table, key, allocation);
194
+ }
195
+
196
+ allocation->count++;
197
+ allocation->memory += rb_obj_memsize_of(object);
198
+
199
+ return allocation;
200
+ }
201
+
202
+ // Returns an array of allocations
203
+ VALUE prof_allocations_wrap(st_table* allocations_table)
204
+ {
205
+ VALUE result = rb_ary_new();
206
+ rb_st_foreach(allocations_table, prof_allocations_collect, result);
207
+ return result;
208
+ }
209
+
210
+ void prof_allocations_unwrap(st_table* allocations_table, VALUE allocations)
211
+ {
212
+ for (int i = 0; i < rb_array_len(allocations); i++)
213
+ {
214
+ VALUE allocation = rb_ary_entry(allocations, i);
215
+ prof_allocation_t* allocation_data = prof_allocation_get(allocation);
216
+ rb_st_insert(allocations_table, allocation_data->key, (st_data_t)allocation_data);
217
+ }
218
+ }
219
+
220
+ /* ====== prof_allocation_t ====== */
221
+ static VALUE prof_allocation_allocate(VALUE klass)
222
+ {
223
+ prof_allocation_t* allocation = prof_allocation_create();
224
+ allocation->object = prof_allocation_wrap(allocation);
225
+ return allocation->object;
226
+ }
227
+
173
228
  /* call-seq:
174
229
  klass -> Class
175
230
 
@@ -238,17 +293,17 @@ static VALUE prof_allocation_memory(VALUE self)
238
293
  /* :nodoc: */
239
294
  static VALUE prof_allocation_dump(VALUE self)
240
295
  {
241
- prof_allocation_t* allocation = prof_get_allocation(self);
296
+ prof_allocation_t* allocation = prof_allocation_get(self);
242
297
 
243
298
  VALUE result = rb_hash_new();
244
299
 
245
- rb_hash_aset(result, ID2SYM(rb_intern("key")), INT2FIX(allocation->key));
300
+ rb_hash_aset(result, ID2SYM(rb_intern("key")), ULL2NUM(allocation->key));
246
301
  rb_hash_aset(result, ID2SYM(rb_intern("klass_name")), prof_allocation_klass_name(self));
247
302
  rb_hash_aset(result, ID2SYM(rb_intern("klass_flags")), INT2FIX(allocation->klass_flags));
248
303
  rb_hash_aset(result, ID2SYM(rb_intern("source_file")), allocation->source_file);
249
304
  rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(allocation->source_line));
250
305
  rb_hash_aset(result, ID2SYM(rb_intern("count")), INT2FIX(allocation->count));
251
- rb_hash_aset(result, ID2SYM(rb_intern("memory")), LONG2FIX(allocation->memory));
306
+ rb_hash_aset(result, ID2SYM(rb_intern("memory")), ULL2NUM(allocation->memory));
252
307
 
253
308
  return result;
254
309
  }
@@ -256,16 +311,16 @@ static VALUE prof_allocation_dump(VALUE self)
256
311
  /* :nodoc: */
257
312
  static VALUE prof_allocation_load(VALUE self, VALUE data)
258
313
  {
259
- prof_allocation_t* allocation = prof_get_allocation(self);
314
+ prof_allocation_t* allocation = prof_allocation_get(self);
260
315
  allocation->object = self;
261
316
 
262
- allocation->key = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
317
+ allocation->key = RB_NUM2ULL(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
263
318
  allocation->klass_name = rb_hash_aref(data, ID2SYM(rb_intern("klass_name")));
264
319
  allocation->klass_flags = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("klass_flags"))));
265
320
  allocation->source_file = rb_hash_aref(data, ID2SYM(rb_intern("source_file")));
266
321
  allocation->source_line = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("source_line"))));
267
322
  allocation->count = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("count"))));
268
- allocation->memory = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("memory"))));
323
+ allocation->memory = NUM2ULONG(rb_hash_aref(data, ID2SYM(rb_intern("memory"))));
269
324
 
270
325
  return data;
271
326
  }
@@ -5,7 +5,6 @@
5
5
  #define _RP_ALLOCATION_
6
6
 
7
7
  #include "ruby_prof.h"
8
- #include "rp_method.h"
9
8
 
10
9
  typedef struct prof_allocation_t
11
10
  {
@@ -20,12 +19,15 @@ typedef struct prof_allocation_t
20
19
  VALUE object; /* Cache to wrapped object */
21
20
  } prof_allocation_t;
22
21
 
22
+ // Allocation (prof_allocation_t*)
23
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);
24
+ prof_allocation_t* prof_allocate_increment(st_table* allocations_table, rb_trace_arg_t* trace_arg);
29
25
 
26
+ // Allocations (st_table*)
27
+ st_table* prof_allocations_create(void);
28
+ VALUE prof_allocations_wrap(st_table* allocations_table);
29
+ void prof_allocations_unwrap(st_table* allocations_table, VALUE allocations);
30
+ void prof_allocations_mark(st_table* allocations_table);
31
+ void prof_allocations_free(st_table* table);
30
32
 
31
33
  #endif //_RP_ALLOCATION_