ruby-prof 1.4.2 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +29 -0
  3. data/README.md +5 -0
  4. data/Rakefile +3 -3
  5. data/ext/ruby_prof/extconf.rb +11 -5
  6. data/ext/ruby_prof/rp_allocation.c +1 -1
  7. data/ext/ruby_prof/rp_call_tree.c +0 -2
  8. data/ext/ruby_prof/rp_call_tree.h +1 -1
  9. data/ext/ruby_prof/rp_measure_allocations.c +10 -13
  10. data/ext/ruby_prof/rp_measure_memory.c +8 -4
  11. data/ext/ruby_prof/rp_measure_process_time.c +7 -6
  12. data/ext/ruby_prof/rp_measurement.c +2 -2
  13. data/ext/ruby_prof/rp_measurement.h +1 -1
  14. data/ext/ruby_prof/rp_method.c +2 -2
  15. data/ext/ruby_prof/rp_method.h +19 -19
  16. data/ext/ruby_prof/rp_profile.c +24 -17
  17. data/ext/ruby_prof/rp_stack.c +1 -1
  18. data/ext/ruby_prof/rp_thread.c +2 -2
  19. data/ext/ruby_prof/vc/ruby_prof.vcxproj +9 -7
  20. data/lib/ruby-prof/assets/call_stack_printer.html.erb +2 -1
  21. data/lib/ruby-prof/printers/abstract_printer.rb +1 -1
  22. data/lib/ruby-prof/printers/call_tree_printer.rb +3 -7
  23. data/lib/ruby-prof/printers/graph_html_printer.rb +1 -1
  24. data/lib/ruby-prof/version.rb +1 -1
  25. data/lib/ruby-prof.rb +1 -1
  26. data/ruby-prof.gemspec +2 -3
  27. data/test/alias_test.rb +97 -101
  28. data/test/duplicate_names_test.rb +4 -4
  29. data/test/dynamic_method_test.rb +23 -9
  30. data/test/gc_test.rb +12 -2
  31. data/test/marshal_test.rb +37 -5
  32. data/test/measure_allocations.rb +1 -5
  33. data/test/measure_allocations_test.rb +27 -69
  34. data/test/{measure_memory_trace_test.rb → measure_memory_test.rb} +57 -470
  35. data/test/measure_process_time_test.rb +1564 -735
  36. data/test/measure_wall_time_test.rb +6 -15
  37. data/test/printer_call_tree_test.rb +2 -2
  38. data/test/printer_flat_test.rb +1 -1
  39. data/test/printers_test.rb +2 -2
  40. data/test/recursive_test.rb +372 -148
  41. data/test/start_stop_test.rb +4 -4
  42. data/test/test_helper.rb +5 -5
  43. data/test/unique_call_path_test.rb +24 -8
  44. data/test/yarv_test.rb +8 -4
  45. metadata +10 -25
  46. data/README.rdoc +0 -5
  47. data/test/measure_allocations_trace_test.rb +0 -375
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e62266e388c4742f279cccfd909bc167b83e2b2bc3438b52254855281ec3b56
4
- data.tar.gz: 4becfdabd8c0453c433f36fcc767a32e5ac50f295c45deaa9b9ed7e09763b8e2
3
+ metadata.gz: '097ef6e369b670ee95682e8f0a11924d3aa67dde85539c3211b40c4d85782022'
4
+ data.tar.gz: 6f91d032ee06ce82f146a4a3db0f7612f7a093517aef891687ac4becda8d20a8
5
5
  SHA512:
6
- metadata.gz: ecdc60504e71f9adc7bcc5df7deb3864e0fad1544cfc57ad225053a205bdb75cad3953a415834761c964e069907e232786f977f667a7492bd7521839a4663bb4
7
- data.tar.gz: d524f3cfa338fb190b362e42d29aaa1b60d1011e84945e73dd6bfc7f5979e0d3fe8702f6135f2c5a3f67ae4dddcd1915e7ddd1db7bab70ee00d22447cb02a398
6
+ metadata.gz: 757f7b033c8ecdb4a12aa94960e87094356722ff69d47afccc74229b520bdbdecd7360f8ae0c4190f24421aa25b0f5f99bb9f3f4efb667706894f68d0b3874cb
7
+ data.tar.gz: be6eca60b902c7629ff5a51c6a5d43e5d1400d4c4dfc04d4e2ddbd48048d5a9d5bde3a5ad185bbc2a843accaa615f09f9f930e78472d09878a79e03610b35f47
data/CHANGES CHANGED
@@ -1,3 +1,32 @@
1
+ 1.4.4 (2022-12-11)
2
+ =====================
3
+ * Update tests for Ruby 3.1 (Charlie Savage)
4
+ * When tracing allocations always use the RUBY_INTERNAL_EVENT_NEWOBJ trace event. Previously GC stats could also be used, but that includes the creation of internal T_IMEMO objects makes reviewing results confusing (Charlie Savage)
5
+ * Remove :profile option that lets a user set the prefix on callgrind output files since KCacheGrind will not automatically show these files in its open dialog. Fixes #313. (Charlie Savage)
6
+ * Don't expose threads to Ruby that don't have a call tree. This can happen when a user is profiling memory usage and then sends a signint to the profiled process. New objects will be created in a new thread, but no method enter/exit trace events are generated by Ruby. Thus the thread has no call tree. Fixes #312 (Charlie Savage)
7
+ * Update github Actions - change 3.0 to '3.0', add Windows mswin (MSP-Greg)
8
+ * Add Ruby 3.1 to test matrix (Charlie Savage)
9
+ * Use normal weight text instead of bold in call strack printer output. Fixes #297 (Charlie Savage)
10
+ * Update VC project to Ruby 3.1 and Visual Studio 2022 (Charlie Savage)
11
+ * Fix marshaling of profile measure. Fixes #315 (Charlie Savage)
12
+ * CI: Omit duplicate 'bundle install'. PR #309 (Olle Jonsson)
13
+ * Fix typo. s/perecent/percent/ (Paarth Madan)
14
+ * Remove support for Ruby 2.5 and 2.6 which are now end of life (Charlie Savage)
15
+
16
+ 1.4.3 (2021-02-16)
17
+ =====================
18
+ * Remove trailing spaces (sergioro)
19
+ * Load "ruby-prof.so" with require_relative (sergioro)
20
+ * Use same file permissions for all test files (sergioro)
21
+ * Create tmp directory for test output (sergioro)
22
+ * Update git-ignore to add mkmf log (sergioro)
23
+ * Fix minitest warning about using MT_CPU instead of N (sergioro)
24
+ * Fix minitest warning "Use assert_nil if expecting nil (sergioro)
25
+ * Add xcode project (Charlie Savage)
26
+ * Update test for Ruby 3.0 (Charlie Savage)
27
+ * Remove Ruby 2.4 support since it is no longer maintained (Charlie Savage)
28
+ * Replace travis status badge with github status badge (Charlie Savage)
29
+
1
30
  1.4.2 (2020-11-3)
2
31
  =====================
3
32
  * Do NOT use Ruby 2.7.0 and 2.7.1 with ruby-prof. A bug in those versions of ruby causes ruby-prof to
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # ruby-prof
2
+
3
+ ![ruby-prof](https://github.com/ruby-prof/ruby-prof/workflows/ruby-prof/badge.svg)
4
+
5
+ For an overview of ruby-prof please see https://ruby-prof.github.io
data/Rakefile CHANGED
@@ -42,7 +42,7 @@ end
42
42
  Rake::Task[:package].enhance [:rdoc]
43
43
 
44
44
  # Setup Windows Gem
45
- if RUBY_PLATFORM.match(/win32|mingw32/)
45
+ if RUBY_PLATFORM.match(/mswin|mingw/)
46
46
  # Windows specification
47
47
  win_spec = default_spec.clone
48
48
  win_spec.platform = Gem::Platform::CURRENT
@@ -65,13 +65,13 @@ RDoc::Task.new("rdoc") do |rdoc|
65
65
  # Show source inline with line numbers
66
66
  rdoc.options << "--line-numbers"
67
67
  # Make the readme file the start page for the generated html
68
- rdoc.options << '--main' << 'README.rdoc'
68
+ rdoc.options << '--main' << 'README.md'
69
69
  rdoc.rdoc_files.include('bin/*',
70
70
  'doc/*.rdoc',
71
71
  'lib/**/*.rb',
72
72
  'ext/ruby_prof/*.c',
73
73
  'ext/ruby_prof/*.h',
74
- 'README.rdoc',
74
+ 'README.md',
75
75
  'LICENSE')
76
76
  end
77
77
 
@@ -1,11 +1,17 @@
1
1
  require "mkmf"
2
2
 
3
- # This function was added in Ruby 2.5, so once Ruby 2.4 is no longer supported this can be removed
4
- have_func('rb_tracearg_callee_id', ["ruby.h"])
3
+ # Let's go with a modern version of C! want to intermix declarations and code (ie, don't define
4
+ # all variables at the top of the method). If using Visual Studio, you'll need 2019 version
5
+ # 16.8 or higher
6
+ if RUBY_PLATFORM =~ /mswin/
7
+ $CFLAGS += ' /std:c11'
8
+ else
9
+ $CFLAGS += ' -std=c11'
10
+ end
5
11
 
6
- # We want to intermix declarations and code (ie, don't define all variables at the top of the method)
7
- unless RUBY_PLATFORM =~ /mswin/
8
- $CFLAGS += ' -std=c99'
12
+ # For gcc add -s to strip symbols, reducing library size from 17MB to 78KB (at least on Windows with mingw64)
13
+ if RUBY_PLATFORM !~ /mswin/
14
+ $LDFLAGS += ' -s'
9
15
  end
10
16
 
11
17
  # And since we are using C99 we want to disable Ruby sending these warnings to gcc
@@ -141,7 +141,7 @@ static const rb_data_type_t allocation_type =
141
141
  },
142
142
  .data = NULL,
143
143
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
144
- };
144
+ };
145
145
 
146
146
  VALUE prof_allocation_wrap(prof_allocation_t* allocation)
147
147
  {
@@ -3,8 +3,6 @@
3
3
 
4
4
  #include "rp_call_tree.h"
5
5
 
6
- #define INITIAL_CALL_TREES_SIZE 2
7
-
8
6
  VALUE cRpCallTree;
9
7
 
10
8
  /* ======= prof_call_tree_t ========*/
@@ -38,6 +38,6 @@ uint32_t prof_call_figure_depth(prof_call_tree_t* call_tree_data);
38
38
  prof_call_tree_t* prof_get_call_tree(VALUE self);
39
39
  VALUE prof_call_tree_wrap(prof_call_tree_t* call_tree);
40
40
  void prof_call_tree_free(prof_call_tree_t* call_tree);
41
- void rp_init_call_tree(void);
41
+ void rp_init_call_tree();
42
42
 
43
43
  #endif //__RP_CALL_TREE_H__
@@ -8,20 +8,20 @@
8
8
  static VALUE cMeasureAllocations;
9
9
  VALUE total_allocated_objects_key;
10
10
 
11
- static double measure_allocations_via_gc_stats(rb_trace_arg_t* trace_arg)
12
- {
13
- return (double)rb_gc_stat(total_allocated_objects_key);
14
- }
15
-
16
- static double measure_allocations_via_tracing(rb_trace_arg_t* trace_arg)
11
+ static double measure_allocations(rb_trace_arg_t* trace_arg)
17
12
  {
18
13
  static double result = 0;
19
14
 
20
15
  if (trace_arg)
21
16
  {
17
+ // Only process creation of new objects
22
18
  rb_event_flag_t event = rb_tracearg_event_flag(trace_arg);
23
- if (event == RUBY_INTERNAL_EVENT_NEWOBJ)
24
- result++;
19
+ if (event == RUBY_INTERNAL_EVENT_NEWOBJ) {
20
+ // Don't count allocations of internal IMemo objects
21
+ VALUE object = rb_tracearg_object(trace_arg);
22
+ if (BUILTIN_TYPE(object) != T_IMEMO)
23
+ result++;
24
+ }
25
25
  }
26
26
  return result;
27
27
  }
@@ -30,14 +30,11 @@ prof_measurer_t* prof_measurer_allocations(bool track_allocations)
30
30
  {
31
31
  prof_measurer_t* measure = ALLOC(prof_measurer_t);
32
32
  measure->mode = MEASURE_ALLOCATIONS;
33
+ measure->measure = measure_allocations;
33
34
  measure->multiplier = 1;
35
+ // Need to track allocations to get RUBY_INTERNAL_EVENT_NEWOBJ event
34
36
  measure->track_allocations = track_allocations;
35
37
 
36
- if (track_allocations)
37
- measure->measure = measure_allocations_via_tracing;
38
- else
39
- measure->measure = measure_allocations_via_gc_stats;
40
-
41
38
  return measure;
42
39
  }
43
40
 
@@ -7,20 +7,23 @@
7
7
 
8
8
  static VALUE cMeasureMemory;
9
9
 
10
- static double
11
- measure_memory_via_tracing(rb_trace_arg_t* trace_arg)
10
+ static double measure_memory(rb_trace_arg_t* trace_arg)
12
11
  {
13
12
  static double result = 0;
14
13
 
15
14
  if (trace_arg)
16
15
  {
16
+ // Only process creation of new objects
17
17
  rb_event_flag_t event = rb_tracearg_event_flag(trace_arg);
18
18
  if (event == RUBY_INTERNAL_EVENT_NEWOBJ)
19
19
  {
20
+ // Don't count allocations of internal IMemo objects
20
21
  VALUE object = rb_tracearg_object(trace_arg);
21
- result += rb_obj_memsize_of(object);
22
+ if (BUILTIN_TYPE(object) != T_IMEMO)
23
+ result += rb_obj_memsize_of(object);
22
24
  }
23
25
  }
26
+
24
27
  return result;
25
28
  }
26
29
 
@@ -28,8 +31,9 @@ prof_measurer_t* prof_measurer_memory(bool track_allocations)
28
31
  {
29
32
  prof_measurer_t* measure = ALLOC(prof_measurer_t);
30
33
  measure->mode = MEASURE_MEMORY;
31
- measure->measure = measure_memory_via_tracing;
34
+ measure->measure = measure_memory;
32
35
  measure->multiplier = 1;
36
+ // Need to track allocations to get RUBY_INTERNAL_EVENT_NEWOBJ event
33
37
  measure->track_allocations = true;
34
38
  return measure;
35
39
  }
@@ -11,21 +11,22 @@ static double measure_process_time(rb_trace_arg_t* trace_arg)
11
11
  #if defined(_WIN32)
12
12
  FILETIME createTime;
13
13
  FILETIME exitTime;
14
- FILETIME sysTime;
14
+ FILETIME kernelTime;
15
15
  FILETIME userTime;
16
16
 
17
- ULARGE_INTEGER sysTimeInt;
17
+ ULARGE_INTEGER kernelTimeInt;
18
18
  ULARGE_INTEGER userTimeInt;
19
19
 
20
- GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &sysTime, &userTime);
20
+ GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
21
21
 
22
- sysTimeInt.LowPart = sysTime.dwLowDateTime;
23
- sysTimeInt.HighPart = sysTime.dwHighDateTime;
22
+ kernelTimeInt.LowPart = kernelTime.dwLowDateTime;
23
+ kernelTimeInt.HighPart = kernelTime.dwHighDateTime;
24
24
  userTimeInt.LowPart = userTime.dwLowDateTime;
25
25
  userTimeInt.HighPart = userTime.dwHighDateTime;
26
26
 
27
- return (double)(sysTimeInt.QuadPart + userTimeInt.QuadPart);
27
+ return (double)(kernelTimeInt.QuadPart + userTimeInt.QuadPart);
28
28
  #elif !defined(CLOCK_PROCESS_CPUTIME_ID)
29
+ #include <sys/resource.h>
29
30
  struct rusage usage;
30
31
  getrusage(RUSAGE_SELF, &usage);
31
32
  return usage.ru_stime.tv_sec + usage.ru_utime.tv_sec + ((usage.ru_stime.tv_usec + usage.ru_utime.tv_usec) / 1000000.0);
@@ -16,7 +16,7 @@ void rp_init_measure_memory(void);
16
16
  void rp_init_measure_process_time(void);
17
17
  void rp_init_measure_wall_time(void);
18
18
 
19
- prof_measurer_t* prof_get_measurer(prof_measure_mode_t measure, bool track_allocations)
19
+ prof_measurer_t* prof_measurer_create(prof_measure_mode_t measure, bool track_allocations)
20
20
  {
21
21
  switch (measure)
22
22
  {
@@ -100,7 +100,7 @@ static const rb_data_type_t measurement_type =
100
100
  },
101
101
  .data = NULL,
102
102
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
103
- };
103
+ };
104
104
 
105
105
  VALUE prof_measurement_wrap(prof_measurement_t* measurement)
106
106
  {
@@ -36,7 +36,7 @@ typedef struct prof_measurement_t
36
36
  VALUE object;
37
37
  } prof_measurement_t;
38
38
 
39
- prof_measurer_t* prof_get_measurer(prof_measure_mode_t measure, bool track_allocations);
39
+ prof_measurer_t* prof_measurer_create(prof_measure_mode_t measure, bool track_allocations);
40
40
  double prof_measure(prof_measurer_t* measurer, rb_trace_arg_t* trace_arg);
41
41
 
42
42
  prof_measurement_t* prof_measurement_create(void);
@@ -253,7 +253,7 @@ static const rb_data_type_t method_info_type =
253
253
  },
254
254
  .data = NULL,
255
255
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
256
- };
256
+ };
257
257
 
258
258
  VALUE prof_method_wrap(prof_method_t* method)
259
259
  {
@@ -488,4 +488,4 @@ void rp_init_method_info()
488
488
 
489
489
  rb_define_method(cRpMethodInfo, "_dump_data", prof_method_dump, 0);
490
490
  rb_define_method(cRpMethodInfo, "_load_data", prof_method_load, 1);
491
- }
491
+ }
@@ -9,35 +9,35 @@
9
9
 
10
10
  extern VALUE cRpMethodInfo;
11
11
 
12
- // Source relation bit offsets.
12
+ // Source relation bit offsets.
13
13
  enum {
14
- kModuleIncludee = 0x1, // Included in module
15
- kClassSingleton = 0x2, // Singleton of a class
16
- kModuleSingleton = 0x4, // Singleton of a module
17
- kObjectSingleton = 0x8, // Singleton of an object
18
- kOtherSingleton = 0x10 // Singleton of unkown object
14
+ kModuleIncludee = 0x1, // Included in module
15
+ kClassSingleton = 0x2, // Singleton of a class
16
+ kModuleSingleton = 0x4, // Singleton of a module
17
+ kObjectSingleton = 0x8, // Singleton of an object
18
+ kOtherSingleton = 0x10 // Singleton of unkown object
19
19
  };
20
20
 
21
- // Profiling information for each method.
22
- // Excluded methods have no call_trees, source_klass, or source_file.
21
+ // Profiling information for each method.
22
+ // Excluded methods have no call_trees, source_klass, or source_file.
23
23
  typedef struct prof_method_t
24
24
  {
25
25
  VALUE profile; // Profile this method is associated with - needed for mark phase
26
- struct prof_call_trees_t* call_trees; // Call infos that call this method
27
- st_table* allocations_table; // Tracks object allocations
26
+ struct prof_call_trees_t* call_trees; // Call infos that call this method
27
+ st_table* allocations_table; // Tracks object allocations
28
28
 
29
- st_data_t key; // Table key
30
- unsigned int klass_flags; // Information about the type of class
31
- VALUE klass; // Resolved klass
32
- VALUE klass_name; // Resolved klass name for this method
33
- VALUE method_name; // Resolved method name for this method
29
+ st_data_t key; // Table key
30
+ unsigned int klass_flags; // Information about the type of class
31
+ VALUE klass; // Resolved klass
32
+ VALUE klass_name; // Resolved klass name for this method
33
+ VALUE method_name; // Resolved method name for this method
34
34
 
35
- VALUE object; // Cached ruby object
35
+ VALUE object; // Cached ruby object
36
36
 
37
37
  bool recursive;
38
- int visits; // Current visits on the stack
39
- VALUE source_file; // Source file
40
- int source_line; // Line number
38
+ int visits; // Current visits on the stack
39
+ VALUE source_file; // Source file
40
+ int source_line; // Line number
41
41
 
42
42
  prof_measurement_t* measurement; // Stores measurement data for this method
43
43
  } prof_method_t;
@@ -138,11 +138,7 @@ prof_method_t* check_method(VALUE profile, rb_trace_arg_t* trace_arg, rb_event_f
138
138
  if (klass == cProfile)
139
139
  return NULL;
140
140
 
141
- #ifdef HAVE_RB_TRACEARG_CALLEE_ID
142
141
  VALUE msym = rb_tracearg_callee_id(trace_arg);
143
- #else
144
- VALUE msym = rb_tracearg_method_id(trace_arg);
145
- #endif
146
142
 
147
143
  st_data_t key = method_key(klass, msym);
148
144
 
@@ -158,7 +154,7 @@ prof_method_t* check_method(VALUE profile, rb_trace_arg_t* trace_arg, rb_event_f
158
154
  int source_line = (event != RUBY_EVENT_C_CALL ? FIX2INT(rb_tracearg_lineno(trace_arg)) : 0);
159
155
  result = create_method(profile, key, klass, msym, source_file, source_line);
160
156
  }
161
-
157
+
162
158
  return result;
163
159
  }
164
160
 
@@ -174,11 +170,7 @@ static void prof_trace(prof_profile_t* profile, rb_trace_arg_t* trace_arg, doubl
174
170
  VALUE source_file = rb_tracearg_path(trace_arg);
175
171
  int source_line = FIX2INT(rb_tracearg_lineno(trace_arg));
176
172
 
177
- #ifdef HAVE_RB_TRACEARG_CALLEE_ID
178
173
  VALUE msym = rb_tracearg_callee_id(trace_arg);
179
- #else
180
- VALUE msym = rb_tracearg_method_id(trace_arg);
181
- #endif
182
174
 
183
175
  unsigned int klass_flags;
184
176
  VALUE klass = rb_tracearg_defined_class(trace_arg);
@@ -219,7 +211,7 @@ static void prof_event_hook(VALUE trace_point, void* data)
219
211
  }
220
212
 
221
213
  /* Special case - skip any methods from the mProf
222
- module since they clutter the results but aren't important to them results. */
214
+ module since they clutter the results but aren't important. */
223
215
  if (self == mProf)
224
216
  return;
225
217
 
@@ -234,6 +226,8 @@ static void prof_event_hook(VALUE trace_point, void* data)
234
226
  {
235
227
  prof_frame_t* frame = prof_frame_current(thread_data->stack);
236
228
 
229
+ /* If there is no frame then this is either the first method being profiled or we have climbed the
230
+ call stack higher than where we started. */
237
231
  if (!frame)
238
232
  {
239
233
  prof_method_t* method = check_method(profile, trace_arg, event, thread_data);
@@ -244,22 +238,24 @@ static void prof_event_hook(VALUE trace_point, void* data)
244
238
  prof_call_tree_t* call_tree = prof_call_tree_create(method, NULL, method->source_file, method->source_line);
245
239
  prof_add_call_tree(method->call_trees, call_tree);
246
240
 
241
+ // We have climbed higher in the stack then where we started
247
242
  if (thread_data->call_tree)
248
243
  {
249
244
  prof_call_tree_add_parent(thread_data->call_tree, call_tree);
250
245
  frame = prof_frame_unshift(thread_data->stack, call_tree, thread_data->call_tree, measurement);
251
246
  }
247
+ // This is the first method to be profiled
252
248
  else
253
249
  {
254
250
  frame = prof_frame_push(thread_data->stack, call_tree, measurement, RTEST(profile_t->paused));
255
251
  }
256
-
252
+
257
253
  thread_data->call_tree = call_tree;
258
254
  }
259
-
255
+
260
256
  frame->source_file = rb_tracearg_path(trace_arg);
261
257
  frame->source_line = FIX2INT(rb_tracearg_lineno(trace_arg));
262
-
258
+
263
259
  break;
264
260
  }
265
261
  case RUBY_EVENT_CALL:
@@ -282,7 +278,7 @@ static void prof_event_hook(VALUE trace_point, void* data)
282
278
  }
283
279
  else if (!frame && thread_data->call_tree)
284
280
  {
285
- // There is no current parent - likely we have returned out of the highest level method we have profiled so far.
281
+ // There is no current parent - likely we have returned out of the highest level method we have profiled so far.
286
282
  // This can happen with enumerators (see fiber_test.rb). So create a new dummy parent.
287
283
  prof_method_t* parent_method = check_parent_method(profile, thread_data);
288
284
  parent_call_tree = prof_call_tree_create(parent_method, NULL, Qnil, 0);
@@ -382,7 +378,7 @@ prof_profile_t* prof_get_profile(VALUE self)
382
378
  static int collect_threads(st_data_t key, st_data_t value, st_data_t result)
383
379
  {
384
380
  thread_data_t* thread_data = (thread_data_t*)value;
385
- if (thread_data->trace)
381
+ if (thread_data->trace && thread_data->call_tree)
386
382
  {
387
383
  VALUE threads_array = (VALUE)result;
388
384
  rb_ary_push(threads_array, prof_thread_wrap(thread_data));
@@ -421,7 +417,7 @@ static void prof_profile_mark(void* data)
421
417
  rb_st_foreach(profile->exclude_methods_tbl, prof_profile_mark_methods, 0);
422
418
  }
423
419
 
424
- /* Freeing the profile creates a cascade of freeing. It frees its threads table, which frees
420
+ /* Freeing the profile creates a cascade of freeing. It frees its threads table, which frees
425
421
  each thread and its associated call treee and methods. */
426
422
  static void prof_profile_ruby_gc_free(void* data)
427
423
  {
@@ -573,7 +569,7 @@ static VALUE prof_initialize(int argc, VALUE* argv, VALUE self)
573
569
  {
574
570
  Check_Type(mode, T_FIXNUM);
575
571
  }
576
- profile->measurer = prof_get_measurer(NUM2INT(mode), track_allocations == Qtrue);
572
+ profile->measurer = prof_measurer_create(NUM2INT(mode), track_allocations == Qtrue);
577
573
  profile->allow_exceptions = (allow_exceptions == Qtrue);
578
574
 
579
575
  if (exclude_threads != Qnil)
@@ -862,8 +858,14 @@ static VALUE prof_exclude_method(VALUE self, VALUE klass, VALUE msym)
862
858
  /* :nodoc: */
863
859
  VALUE prof_profile_dump(VALUE self)
864
860
  {
861
+ prof_profile_t* profile = prof_get_profile(self);
862
+
865
863
  VALUE result = rb_hash_new();
866
864
  rb_hash_aset(result, ID2SYM(rb_intern("threads")), prof_threads(self));
865
+ rb_hash_aset(result, ID2SYM(rb_intern("measurer_mode")), INT2NUM(profile->measurer->mode));
866
+ rb_hash_aset(result, ID2SYM(rb_intern("measurer_track_allocations")),
867
+ profile->measurer->track_allocations ? Qtrue : Qfalse);
868
+
867
869
  return result;
868
870
  }
869
871
 
@@ -872,6 +874,11 @@ VALUE prof_profile_load(VALUE self, VALUE data)
872
874
  {
873
875
  prof_profile_t* profile = prof_get_profile(self);
874
876
 
877
+ VALUE measurer_mode = rb_hash_aref(data, ID2SYM(rb_intern("measurer_mode")));
878
+ VALUE measurer_track_allocations = rb_hash_aref(data, ID2SYM(rb_intern("measurer_track_allocations")));
879
+ profile->measurer = prof_measurer_create((prof_measure_mode_t)(NUM2INT(measurer_mode)),
880
+ measurer_track_allocations == Qtrue ? true : false);
881
+
875
882
  VALUE threads = rb_hash_aref(data, ID2SYM(rb_intern("threads")));
876
883
  for (int i = 0; i < rb_array_len(threads); i++)
877
884
  {
@@ -180,7 +180,7 @@ prof_frame_t* prof_frame_pop(prof_stack_t* stack, double measurement)
180
180
  call_tree->measurement->total_time += total_time;
181
181
 
182
182
  call_tree->visits--;
183
-
183
+
184
184
  prof_frame_t* parent_frame = prof_stack_last(stack);
185
185
  if (parent_frame)
186
186
  {
@@ -21,7 +21,7 @@ You cannot create an instance of RubyProf::Thread, instead you access it from a
21
21
 
22
22
  VALUE cRpThread;
23
23
 
24
- // ====== thread_data_t ======
24
+ // ====== thread_data_t ======
25
25
  thread_data_t* thread_data_create(void)
26
26
  {
27
27
  thread_data_t* result = ALLOC(thread_data_t);
@@ -146,7 +146,7 @@ thread_data_t* prof_get_thread(VALUE self)
146
146
  }
147
147
 
148
148
  // ====== Thread Table ======
149
- // The thread table is hash keyed on ruby fiber_id that stores instances of thread_data_t.
149
+ // The thread table is hash keyed on ruby fiber_id that stores instances of thread_data_t.
150
150
 
151
151
  st_table* threads_table_create()
152
152
  {
@@ -29,19 +29,21 @@
29
29
  <ConfigurationType>DynamicLibrary</ConfigurationType>
30
30
  <UseDebugLibraries>true</UseDebugLibraries>
31
31
  <CharacterSet>Unicode</CharacterSet>
32
+ <PlatformToolset>v143</PlatformToolset>
32
33
  </PropertyGroup>
33
34
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
34
35
  <ConfigurationType>DynamicLibrary</ConfigurationType>
35
36
  <UseDebugLibraries>false</UseDebugLibraries>
36
37
  <WholeProgramOptimization>true</WholeProgramOptimization>
37
38
  <CharacterSet>Unicode</CharacterSet>
39
+ <PlatformToolset>v143</PlatformToolset>
38
40
  </PropertyGroup>
39
41
  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
40
- <PlatformToolset>v142</PlatformToolset>
42
+ <PlatformToolset>v143</PlatformToolset>
41
43
  <ConfigurationType>DynamicLibrary</ConfigurationType>
42
44
  </PropertyGroup>
43
45
  <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
44
- <PlatformToolset>v142</PlatformToolset>
46
+ <PlatformToolset>v143</PlatformToolset>
45
47
  </PropertyGroup>
46
48
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
47
49
  <ImportGroup Label="ExtensionSettings">
@@ -64,7 +66,7 @@
64
66
  </PropertyGroup>
65
67
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
66
68
  <TargetExt>.so</TargetExt>
67
- <OutDir>..\..\..\lib\</OutDir>
69
+ <OutDir>$(SolutionDir)\..</OutDir>
68
70
  </PropertyGroup>
69
71
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
70
72
  <ClCompile>
@@ -102,14 +104,14 @@
102
104
  </ItemDefinitionGroup>
103
105
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
104
106
  <ClCompile>
105
- <AdditionalIncludeDirectories>C:\msys64\usr\local\ruby-2.7.2vc\include\ruby-2.7.0\x64-mswin64_140;C:\msys64\usr\local\ruby-2.7.2vc\include\ruby-2.7.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
107
+ <AdditionalIncludeDirectories>C:\msys64\usr\local\ruby-3.1.2-vc\include\ruby-3.1.0\x64-mswin64_140;C:\msys64\usr\local\ruby-3.1.2-vc\include\ruby-3.1.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
106
108
  <Optimization>Disabled</Optimization>
107
- <PreprocessorDefinitions>HAVE_RB_TRACEARG_CALLEE_ID;%(PreprocessorDefinitions)</PreprocessorDefinitions>
109
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
108
110
  <WarningLevel>Level3</WarningLevel>
109
111
  </ClCompile>
110
112
  <Link>
111
- <AdditionalLibraryDirectories>C:\msys64\usr\local\ruby-2.7.2vc\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
112
- <AdditionalDependencies>x64-vcruntime140-ruby270.lib;%(AdditionalDependencies)</AdditionalDependencies>
113
+ <AdditionalLibraryDirectories>C:\msys64\usr\local\ruby-3.1.2-vc\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
114
+ <AdditionalDependencies>x64-vcruntime140-ruby310.lib;%(AdditionalDependencies)</AdditionalDependencies>
113
115
  <ModuleDefinitionFile>ruby_prof.def</ModuleDefinitionFile>
114
116
  <SubSystem>Console</SubSystem>
115
117
  </Link>
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
5
5
  <title>ruby-prof call tree</title>
6
- <style type="text/css">
6
+ <style>
7
7
  body {
8
8
  font-size: 70%;
9
9
  padding: 0;
@@ -19,6 +19,7 @@
19
19
  margin-bottom: 0px;
20
20
  padding-left: 0px;
21
21
  list-style-type: none;
22
+ font-weight: normal;
22
23
  }
23
24
 
24
25
  li {
@@ -113,7 +113,7 @@ module RubyProf
113
113
 
114
114
  def print_footer(thread)
115
115
  @output << <<~EOT
116
-
116
+
117
117
  * recursively called methods
118
118
 
119
119
  Columns are:
@@ -100,21 +100,17 @@ module RubyProf
100
100
  true
101
101
  end
102
102
 
103
- def base_name
104
- @options[:profile] || "profile"
105
- end
106
-
107
103
  def remove_subsidiary_files_from_previous_profile_runs
108
- pattern = [base_name, "callgrind.out", $$, "*"].join(".")
104
+ pattern = ["callgrind.out", $$, "*"].join(".")
109
105
  files = Dir.glob(File.join(path, pattern))
110
106
  FileUtils.rm_f(files)
111
107
  end
112
108
 
113
109
  def file_name_for_thread(thread)
114
110
  if thread.fiber_id == Fiber.current.object_id
115
- [base_name, "callgrind.out", $$].join(".")
111
+ ["callgrind.out", $$].join(".")
116
112
  else
117
- [base_name, "callgrind.out", $$, thread.fiber_id].join(".")
113
+ ["callgrind.out", $$, thread.fiber_id].join(".")
118
114
  end
119
115
  end
120
116
 
@@ -29,7 +29,7 @@ module RubyProf
29
29
  end
30
30
 
31
31
  # Creates a link to a method. Note that we do not create
32
- # links to methods which are under the min_perecent
32
+ # links to methods which are under the min_percent
33
33
  # specified by the user, since they will not be
34
34
  # printed out.
35
35
  def create_link(thread, overall_time, method)
@@ -1,3 +1,3 @@
1
1
  module RubyProf
2
- VERSION = "1.4.2"
2
+ VERSION = "1.4.4"
3
3
  end
data/lib/ruby-prof.rb CHANGED
@@ -6,7 +6,7 @@ begin
6
6
  version = Gem::Version.new(RUBY_VERSION)
7
7
  require "#{version.segments[0..1].join('.')}/ruby_prof.so"
8
8
  rescue LoadError
9
- require "ruby_prof.so"
9
+ require_relative "../ext/ruby_prof/ruby_prof.so"
10
10
  end
11
11
 
12
12
  require 'ruby-prof/version'