ruby-prof 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9dbafd0a6aebb3d09c5f7f198d4261fbd39709c33ec216ea542e8fe2063cd2b9
4
- data.tar.gz: f66379b3e8b2c5fde1ef01ce84484a6b9f958bb643c4783e32fd6b37f033efb0
3
+ metadata.gz: 756de796c2629622138d38034f1c895b2d2e32e8e00f1ef3d7b9bad2210b4cc2
4
+ data.tar.gz: 686d22e4138b8fbe4a03f9ba8bfcd1e5523671fb5b4a3f46029676339a2736b8
5
5
  SHA512:
6
- metadata.gz: 134cb10903895675ccfa34ab880ecdcd04bf55d8b749fff2f431655777b1801820e0a68c5b402d5200beb0c2e942d5833cac6a2faaa897a9be36c5b2531e30d2
7
- data.tar.gz: '09400b5f8f70abb628984dff8cd270bfb490db686f06d89530ee25a68c9e5cf7546da429ca48570cfa57e73af092ca38964fa64fb30e3b987a1fa1503b212047'
6
+ metadata.gz: 0fdfc46eb05543b5e6fa0ea1e669c390561074f2c9a0a3e5e2d109ee5cf713ad1bd663dd842bf2f8dc973c88f95838cd94b564e9e5e517fcc81daf8325751396
7
+ data.tar.gz: '058817625f1294f32d1aaba1dcc5f607d9375ec85177f69461be92a9fda972765f211e2d385514360779d6a034f15b4966de082c22d8017a3889c2a856aadd3b'
data/CHANGES CHANGED
@@ -1,3 +1,10 @@
1
+ 1.4.0 (2020-05-12)
2
+ =====================
3
+ * API change - remove merge_fibers support since it resulted in incorrect results or crashes (Charlie Savage)
4
+ * Fix crash when profiling memory usage (Charlie Savage)
5
+ * When tracing execution correctly print out newobj tracepoint events (Charlie Savage)
6
+ * Remove no longer needed code for building extensions (Charlie Savage)
7
+
1
8
  1.3.2 (2020-04-19)
2
9
  =====================
3
10
  * Fix rack profiler so it is thread safe (Charlie Savage)
@@ -1,35 +1,5 @@
1
1
  require "mkmf"
2
2
 
3
- if RUBY_ENGINE != "ruby"
4
- STDERR.puts("\n\n***** This gem is MRI-specific. It does not support #{RUBY_ENGINE}. *****\n\n")
5
- exit(1)
6
- end
7
-
8
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4.0')
9
- STDERR.puts("\n\n***** Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to 2.3 or higher. *****\n\n")
10
- exit(1)
11
- end
12
-
13
- # For the love of bitfields...
14
- $CFLAGS += ' -std=c99'
15
-
16
- # And since we are using C99
17
- CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
18
-
19
- def add_define(name, value = nil)
20
- if value
21
- $defs.push("-D#{name}=#{value}")
22
- else
23
- $defs.push("-D#{name}")
24
- end
25
- end
26
-
27
- def windows?
28
- RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
29
- end
30
-
31
- add_define("RUBY_PROF_RUBY_VERSION", RUBY_VERSION.split('.')[0..2].inject(0){|v,d| v*100+d.to_i})
32
-
33
3
  # This function was added in Ruby 2.5, so once Ruby 2.4 is no longer supported this can be removed
34
4
  have_func('rb_tracearg_callee_id', ["ruby.h"])
35
5
 
@@ -219,7 +219,7 @@ VALUE prof_call_trees_callers(VALUE self)
219
219
  }
220
220
  }
221
221
 
222
- VALUE result = rb_ary_new_capa(callers->num_entries);
222
+ VALUE result = rb_ary_new_capa((long)callers->num_entries);
223
223
  rb_st_foreach(callers, prof_call_trees_collect_aggregates, result);
224
224
  rb_st_free_table(callers);
225
225
  return result;
@@ -239,7 +239,7 @@ VALUE prof_call_trees_callees(VALUE self)
239
239
  rb_st_foreach((*call_tree)->children, prof_call_trees_collect_callees, (st_data_t)callees);
240
240
  }
241
241
 
242
- VALUE result = rb_ary_new_capa(callees->num_entries);
242
+ VALUE result = rb_ary_new_capa((long)callees->num_entries);
243
243
  rb_st_foreach(callees, prof_call_trees_collect_aggregates, result);
244
244
  rb_st_free_table(callees);
245
245
  return result;
@@ -10,7 +10,7 @@ VALUE total_allocated_objects_key;
10
10
 
11
11
  static double measure_allocations_via_gc_stats(rb_trace_arg_t* trace_arg)
12
12
  {
13
- return rb_gc_stat(total_allocated_objects_key);
13
+ return (double)rb_gc_stat(total_allocated_objects_key);
14
14
  }
15
15
 
16
16
  static double measure_allocations_via_tracing(rb_trace_arg_t* trace_arg)
@@ -24,7 +24,7 @@ static double measure_process_time(rb_trace_arg_t* trace_arg)
24
24
  userTimeInt.LowPart = userTime.dwLowDateTime;
25
25
  userTimeInt.HighPart = userTime.dwHighDateTime;
26
26
 
27
- return sysTimeInt.QuadPart + userTimeInt.QuadPart;
27
+ return (double)(sysTimeInt.QuadPart + userTimeInt.QuadPart);
28
28
  #elif !defined(CLOCK_PROCESS_CPUTIME_ID)
29
29
  struct rusage usage;
30
30
  getrusage(RUSAGE_SELF, &usage);
@@ -17,7 +17,7 @@ static double measure_wall_time(rb_trace_arg_t* trace_arg)
17
17
  #if defined(_WIN32)
18
18
  LARGE_INTEGER time;
19
19
  QueryPerformanceCounter(&time);
20
- return time.QuadPart;
20
+ return (double)time.QuadPart;
21
21
  #elif defined(__APPLE__)
22
22
  return mach_absolute_time();// * (uint64_t)mach_timebase.numer / (uint64_t)mach_timebase.denom;
23
23
  #elif defined(__linux__)
@@ -65,25 +65,19 @@ static const char* get_event_name(rb_event_flag_t event)
65
65
  return "fiber-switch";
66
66
  case RUBY_EVENT_RAISE:
67
67
  return "raise";
68
+ case RUBY_INTERNAL_EVENT_NEWOBJ:
69
+ return "newobj";
68
70
  default:
69
71
  return "unknown";
70
72
  }
71
73
  }
72
74
 
73
- VALUE get_fiber(prof_profile_t* profile)
74
- {
75
- if (profile->merge_fibers)
76
- return rb_thread_current();
77
- else
78
- return rb_fiber_current();
79
- }
80
-
81
75
  thread_data_t* check_fiber(prof_profile_t* profile, double measurement)
82
76
  {
83
77
  thread_data_t* result = NULL;
84
78
 
85
- /* Get the current thread and fiber information. */
86
- VALUE fiber = get_fiber(profile);
79
+ // Get the current fiber
80
+ VALUE fiber = rb_fiber_current();
87
81
 
88
82
  /* We need to switch the profiling context if we either had none before,
89
83
  we don't merge fibers and the fiber ids differ, or the thread ids differ. */
@@ -172,7 +166,7 @@ prof_method_t* check_method(VALUE profile, rb_trace_arg_t* trace_arg, rb_event_f
172
166
  static void prof_trace(prof_profile_t* profile, rb_trace_arg_t* trace_arg, double measurement)
173
167
  {
174
168
  static VALUE last_fiber = Qnil;
175
- VALUE fiber = get_fiber(profile);
169
+ VALUE fiber = rb_fiber_current();
176
170
 
177
171
  rb_event_flag_t event = rb_tracearg_event_flag(trace_arg);
178
172
  const char* event_name = get_event_name(event);
@@ -487,7 +481,6 @@ static VALUE prof_allocate(VALUE klass)
487
481
  profile->include_threads_tbl = NULL;
488
482
  profile->running = Qfalse;
489
483
  profile->allow_exceptions = false;
490
- profile->merge_fibers = false;
491
484
  profile->exclude_methods_tbl = method_table_create();
492
485
  profile->running = Qfalse;
493
486
  profile->tracepoints = rb_ary_new();
@@ -529,9 +522,6 @@ prof_stop_threads(prof_profile_t* profile)
529
522
  If not specified, defaults to RubyProf::WALL_TIME.
530
523
  allow_exceptions: Whether to raise exceptions encountered during profiling,
531
524
  or to suppress all exceptions during profiling
532
- merge_fibers: Whether profiling data for a given thread's fibers should all be
533
- subsumed under a single entry. Basically only useful to produce
534
- callgrind profiles.
535
525
  track_allocations: Whether to track object allocations while profiling. True or false.
536
526
  exclude_common: Exclude common methods from the profile. True or false.
537
527
  exclude_threads: Threads to exclude from the profiling results.
@@ -546,7 +536,6 @@ static VALUE prof_initialize(int argc, VALUE* argv, VALUE self)
546
536
  VALUE include_threads = Qnil;
547
537
  VALUE exclude_common = Qnil;
548
538
  VALUE allow_exceptions = Qfalse;
549
- VALUE merge_fibers = Qfalse;
550
539
  VALUE track_allocations = Qfalse;
551
540
 
552
541
  int i;
@@ -566,7 +555,6 @@ static VALUE prof_initialize(int argc, VALUE* argv, VALUE self)
566
555
  mode = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("measure_mode")));
567
556
  track_allocations = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("track_allocations")));
568
557
  allow_exceptions = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("allow_exceptions")));
569
- merge_fibers = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("merge_fibers")));
570
558
  exclude_common = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("exclude_common")));
571
559
  exclude_threads = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("exclude_threads")));
572
560
  include_threads = rb_hash_aref(mode_or_options, ID2SYM(rb_intern("include_threads")));
@@ -587,7 +575,6 @@ static VALUE prof_initialize(int argc, VALUE* argv, VALUE self)
587
575
  }
588
576
  profile->measurer = prof_get_measurer(NUM2INT(mode), track_allocations == Qtrue);
589
577
  profile->allow_exceptions = (allow_exceptions == Qtrue);
590
- profile->merge_fibers = (merge_fibers == Qtrue);
591
578
 
592
579
  if (exclude_threads != Qnil)
593
580
  {
@@ -679,7 +666,7 @@ static VALUE prof_start(VALUE self)
679
666
 
680
667
  profile->running = Qtrue;
681
668
  profile->paused = Qfalse;
682
- profile->last_thread_data = threads_table_insert(profile, get_fiber(profile));
669
+ profile->last_thread_data = threads_table_insert(profile, rb_fiber_current());
683
670
 
684
671
  /* open trace file if environment wants it */
685
672
  trace_file_name = getenv("RUBY_PROF_TRACE");
@@ -769,11 +756,7 @@ static VALUE prof_stop(VALUE self)
769
756
  {
770
757
  if (trace_file != stderr && trace_file != stdout)
771
758
  {
772
- #ifdef _MSC_VER
773
- _fcloseall();
774
- #else
775
759
  fclose(trace_file);
776
- #endif
777
760
  }
778
761
  trace_file = NULL;
779
762
  }
@@ -26,7 +26,6 @@ typedef struct prof_profile_t
26
26
  thread_data_t* last_thread_data;
27
27
  double measurement_at_pause_resume;
28
28
  bool allow_exceptions;
29
- bool merge_fibers;
30
29
  } prof_profile_t;
31
30
 
32
31
  void rp_init_profile(void);
@@ -129,7 +129,7 @@ prof_frame_t* prof_frame_push(prof_stack_t* stack, prof_call_tree_t* call_tree,
129
129
  prof_frame_t* prof_frame_unshift(prof_stack_t* stack, prof_call_tree_t* parent_call_tree, prof_call_tree_t* call_tree, double measurement)
130
130
  {
131
131
  if (prof_stack_last(stack))
132
- rb_raise(rb_eRuntimeError, "Stach unshift can only be called with an empty stack");
132
+ rb_raise(rb_eRuntimeError, "Stack unshift can only be called with an empty stack");
133
133
 
134
134
  parent_call_tree->measurement->total_time = call_tree->measurement->total_time;
135
135
  parent_call_tree->measurement->self_time = 0;
@@ -187,7 +187,7 @@ prof_frame_t* prof_frame_pop(prof_stack_t* stack, double measurement)
187
187
 
188
188
  prof_method_t* prof_find_method(prof_stack_t* stack, VALUE source_file, int source_line)
189
189
  {
190
- prof_frame_t* frame = stack->ptr;
190
+ prof_frame_t* frame = prof_stack_last(stack);
191
191
  while (frame >= stack->start)
192
192
  {
193
193
  if (!frame->call_tree)
@@ -7,16 +7,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ruby_prof", "ruby_prof.vcxp
7
7
  EndProject
8
8
  Global
9
9
  GlobalSection(SolutionConfigurationPlatforms) = preSolution
10
+ Debug|ARM = Debug|ARM
11
+ Debug|ARM64 = Debug|ARM64
10
12
  Debug|x64 = Debug|x64
11
13
  Debug|x86 = Debug|x86
14
+ Release|ARM = Release|ARM
15
+ Release|ARM64 = Release|ARM64
12
16
  Release|x64 = Release|x64
13
17
  Release|x86 = Release|x86
14
18
  EndGlobalSection
15
19
  GlobalSection(ProjectConfigurationPlatforms) = postSolution
20
+ {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Debug|ARM.ActiveCfg = Debug|Win32
21
+ {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Debug|ARM64.ActiveCfg = Debug|Win32
16
22
  {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Debug|x64.ActiveCfg = Debug|x64
17
23
  {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Debug|x64.Build.0 = Debug|x64
18
24
  {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Debug|x86.ActiveCfg = Debug|Win32
19
25
  {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Debug|x86.Build.0 = Debug|Win32
26
+ {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Release|ARM.ActiveCfg = Release|Win32
27
+ {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Release|ARM64.ActiveCfg = Release|Win32
20
28
  {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Release|x64.ActiveCfg = Release|x64
21
29
  {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Release|x64.Build.0 = Release|x64
22
30
  {6B4978F4-3B5F-4D38-81A8-069EC28CC069}.Release|x86.ActiveCfg = Release|Win32
@@ -64,7 +64,7 @@
64
64
  </PropertyGroup>
65
65
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
66
66
  <TargetExt>.so</TargetExt>
67
- <OutDir>..\..\..\lib</OutDir>
67
+ <OutDir>..\..\..\lib\</OutDir>
68
68
  </PropertyGroup>
69
69
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
70
70
  <ClCompile>
@@ -102,17 +102,28 @@
102
102
  </ItemDefinitionGroup>
103
103
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
104
104
  <ClCompile>
105
- <AdditionalIncludeDirectories>C:\msys64\usr\local\ruby-2.7.0vc\include\ruby-2.7.0\x64-mswin64_140;C:\msys64\usr\local\ruby-2.7.0vc\include\ruby-2.7.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
105
+ <AdditionalIncludeDirectories>C:\msys64\usr\local\ruby-2.7.1vc\include\ruby-2.7.0\x64-mswin64_140;C:\msys64\usr\local\ruby-2.7.1vc\include\ruby-2.7.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
106
106
  <Optimization>Disabled</Optimization>
107
107
  <PreprocessorDefinitions>HAVE_RB_TRACEARG_CALLEE_ID;%(PreprocessorDefinitions)</PreprocessorDefinitions>
108
+ <WarningLevel>Level3</WarningLevel>
108
109
  </ClCompile>
109
110
  <Link>
110
- <AdditionalLibraryDirectories>C:\msys64\usr\local\ruby-2.7.0vc\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
111
+ <AdditionalLibraryDirectories>C:\msys64\usr\local\ruby-2.7.1vc\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
111
112
  <AdditionalDependencies>x64-vcruntime140-ruby270.lib;%(AdditionalDependencies)</AdditionalDependencies>
112
113
  <ModuleDefinitionFile>ruby_prof.def</ModuleDefinitionFile>
113
114
  <SubSystem>Console</SubSystem>
114
115
  </Link>
115
116
  </ItemDefinitionGroup>
117
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
118
+ <ClCompile>
119
+ <AdditionalIncludeDirectories>C:\msys64\usr\local\ruby-2.7.1vc\include\ruby-2.7.0\x64-mswin64_140;C:\msys64\usr\local\ruby-2.7.1vc\include\ruby-2.7.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
120
+ </ClCompile>
121
+ <Link>
122
+ <AdditionalLibraryDirectories>C:\msys64\usr\local\ruby-2.7.1vc\lib</AdditionalLibraryDirectories>
123
+ <AdditionalDependencies>x64-vcruntime140-ruby270.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
124
+ <ModuleDefinitionFile>ruby_prof.def</ModuleDefinitionFile>
125
+ </Link>
126
+ </ItemDefinitionGroup>
116
127
  <ItemGroup>
117
128
  <ClInclude Include="..\rp_aggregate_call_tree.h" />
118
129
  <ClInclude Include="..\rp_allocation.h" />
@@ -0,0 +1,132 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+ <ItemGroup Label="ProjectConfigurations">
4
+ <ProjectConfiguration Include="Debug|ARM">
5
+ <Configuration>Debug</Configuration>
6
+ <Platform>ARM</Platform>
7
+ </ProjectConfiguration>
8
+ <ProjectConfiguration Include="Release|ARM">
9
+ <Configuration>Release</Configuration>
10
+ <Platform>ARM</Platform>
11
+ </ProjectConfiguration>
12
+ <ProjectConfiguration Include="Debug|ARM64">
13
+ <Configuration>Debug</Configuration>
14
+ <Platform>ARM64</Platform>
15
+ </ProjectConfiguration>
16
+ <ProjectConfiguration Include="Release|ARM64">
17
+ <Configuration>Release</Configuration>
18
+ <Platform>ARM64</Platform>
19
+ </ProjectConfiguration>
20
+ <ProjectConfiguration Include="Debug|x86">
21
+ <Configuration>Debug</Configuration>
22
+ <Platform>x86</Platform>
23
+ </ProjectConfiguration>
24
+ <ProjectConfiguration Include="Release|x86">
25
+ <Configuration>Release</Configuration>
26
+ <Platform>x86</Platform>
27
+ </ProjectConfiguration>
28
+ <ProjectConfiguration Include="Debug|x64">
29
+ <Configuration>Debug</Configuration>
30
+ <Platform>x64</Platform>
31
+ </ProjectConfiguration>
32
+ <ProjectConfiguration Include="Release|x64">
33
+ <Configuration>Release</Configuration>
34
+ <Platform>x64</Platform>
35
+ </ProjectConfiguration>
36
+ </ItemGroup>
37
+ <PropertyGroup Label="Globals">
38
+ <ProjectGuid>{fd79d690-c808-464c-a46b-01188609976e}</ProjectGuid>
39
+ <Keyword>Linux</Keyword>
40
+ <RootNamespace>Project1</RootNamespace>
41
+ <MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
42
+ <ApplicationType>Linux</ApplicationType>
43
+ <ApplicationTypeRevision>1.0</ApplicationTypeRevision>
44
+ <TargetLinuxPlatform>Generic</TargetLinuxPlatform>
45
+ <LinuxProjectType>{2238F9CD-F817-4ECC-BD14-2524D2669B35}</LinuxProjectType>
46
+ </PropertyGroup>
47
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
48
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
49
+ <UseDebugLibraries>true</UseDebugLibraries>
50
+ </PropertyGroup>
51
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
52
+ <UseDebugLibraries>false</UseDebugLibraries>
53
+ </PropertyGroup>
54
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
55
+ <UseDebugLibraries>true</UseDebugLibraries>
56
+ </PropertyGroup>
57
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
58
+ <UseDebugLibraries>false</UseDebugLibraries>
59
+ </PropertyGroup>
60
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
61
+ <UseDebugLibraries>true</UseDebugLibraries>
62
+ <PlatformToolset>WSL_1_0</PlatformToolset>
63
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
64
+ </PropertyGroup>
65
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
66
+ <UseDebugLibraries>false</UseDebugLibraries>
67
+ <PlatformToolset>WSL_1_0</PlatformToolset>
68
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
69
+ </PropertyGroup>
70
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
71
+ <UseDebugLibraries>false</UseDebugLibraries>
72
+ </PropertyGroup>
73
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
74
+ <UseDebugLibraries>true</UseDebugLibraries>
75
+ </PropertyGroup>
76
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
77
+ <ImportGroup Label="ExtensionSettings" />
78
+ <ImportGroup Label="Shared" />
79
+ <ImportGroup Label="PropertySheets" />
80
+ <PropertyGroup Label="UserMacros" />
81
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
82
+ <TargetName>ruby_prof</TargetName>
83
+ <OutDir>../usr/local/lib64/gems/ruby/ruby-prof-1.3.2/</OutDir>
84
+ </PropertyGroup>
85
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
86
+ <TargetName>ruby_prof</TargetName>
87
+ </PropertyGroup>
88
+ <ItemGroup>
89
+ <ClInclude Include="..\rp_aggregate_call_tree.h" />
90
+ <ClInclude Include="..\rp_allocation.h" />
91
+ <ClInclude Include="..\rp_call_tree.h" />
92
+ <ClInclude Include="..\rp_call_trees.h" />
93
+ <ClInclude Include="..\rp_measurement.h" />
94
+ <ClInclude Include="..\rp_method.h" />
95
+ <ClInclude Include="..\rp_profile.h" />
96
+ <ClInclude Include="..\rp_stack.h" />
97
+ <ClInclude Include="..\rp_thread.h" />
98
+ <ClInclude Include="..\ruby_prof.h" />
99
+ </ItemGroup>
100
+ <ItemGroup>
101
+ <ClCompile Include="..\rp_aggregate_call_tree.c" />
102
+ <ClCompile Include="..\rp_allocation.c" />
103
+ <ClCompile Include="..\rp_call_tree.c" />
104
+ <ClCompile Include="..\rp_call_trees.c" />
105
+ <ClCompile Include="..\rp_measurement.c" />
106
+ <ClCompile Include="..\rp_measure_allocations.c" />
107
+ <ClCompile Include="..\rp_measure_memory.c" />
108
+ <ClCompile Include="..\rp_measure_process_time.c" />
109
+ <ClCompile Include="..\rp_measure_wall_time.c" />
110
+ <ClCompile Include="..\rp_method.c" />
111
+ <ClCompile Include="..\rp_profile.c" />
112
+ <ClCompile Include="..\rp_stack.c" />
113
+ <ClCompile Include="..\rp_thread.c" />
114
+ <ClCompile Include="..\ruby_prof.c" />
115
+ </ItemGroup>
116
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
117
+ <Link>
118
+ <LibraryDependencies>ruby</LibraryDependencies>
119
+ </Link>
120
+ <ClCompile>
121
+ <PreprocessorDefinitions>
122
+ </PreprocessorDefinitions>
123
+ </ClCompile>
124
+ </ItemDefinitionGroup>
125
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
126
+ <Link>
127
+ <LibraryDependencies>ruby</LibraryDependencies>
128
+ </Link>
129
+ </ItemDefinitionGroup>
130
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
131
+ <ImportGroup Label="ExtensionTargets" />
132
+ </Project>
@@ -1,3 +1,3 @@
1
1
  module RubyProf
2
- VERSION = "1.3.2"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -0,0 +1,9 @@
1
+ # tcp_client.rb
2
+ require 'socket'
3
+ client = TCPSocket.new('localhost', 9090)
4
+
5
+ client.puts("HI")
6
+ line = client.gets
7
+ puts line
8
+
9
+ client.close
@@ -8,254 +8,122 @@ require 'set'
8
8
 
9
9
  # -- Tests ----
10
10
  class FiberTest < TestCase
11
+
11
12
  def enumerator_with_fibers
12
- @fiber_ids << Fiber.current.object_id
13
13
  enum = Enumerator.new do |yielder|
14
14
  [1,2].each do |x|
15
- @fiber_ids << Fiber.current.object_id
16
- sleep 0.1
17
15
  yielder.yield x
18
16
  end
19
17
  end
20
- while true
21
- begin
22
- enum.next
23
- rescue StopIteration
24
- break
25
- end
26
- end
27
- sleep 0.1
18
+
19
+ enum.next
20
+ enum.next
21
+ end
22
+
23
+ def fiber_yield_resume
24
+ fiber = Fiber.new do
25
+ Fiber.yield 1
26
+ Fiber.yield 2
27
+ end
28
+
29
+ fiber.resume
30
+ fiber.resume
28
31
  end
29
32
 
30
33
  def setup
31
34
  # Need to use wall time for this test due to the sleep calls
32
35
  RubyProf::measure_mode = RubyProf::WALL_TIME
33
- @fiber_ids = Set.new
34
- @root_fiber = Fiber.current.object_id
35
- @thread_id = Thread.current.object_id
36
36
  end
37
37
 
38
38
  def test_fibers
39
39
  result = RubyProf.profile { enumerator_with_fibers }
40
40
 
41
- profiled_fiber_ids = result.threads.map(&:fiber_id)
42
- assert_equal(2, result.threads.length)
43
- assert_equal([@thread_id], result.threads.map(&:id).uniq)
44
- assert_equal(@fiber_ids, Set.new(profiled_fiber_ids))
41
+ assert_equal(2, result.threads.size)
45
42
 
46
- assert profiled_fiber_ids.include?(@root_fiber)
47
- assert(root_fiber_profile = result.threads.detect{|t| t.fiber_id == @root_fiber})
48
- assert(enum_fiber_profile = result.threads.detect{|t| t.fiber_id != @root_fiber})
49
- assert_in_delta(0.33, root_fiber_profile.total_time, 0.05)
50
- assert_in_delta(0.33, enum_fiber_profile.total_time, 0.05)
51
-
52
- methods = result.threads[0].methods.sort.reverse
53
- assert_equal(12, methods.count)
43
+ thread1 = result.threads[0]
44
+ methods = thread1.methods.sort.reverse
45
+ assert_equal(5, methods.count)
54
46
 
55
47
  method = methods[0]
56
48
  assert_equal('FiberTest#test_fibers', method.full_name)
57
49
  assert_equal(1, method.called)
58
- assert_in_delta(0.33, method.total_time, 0.05)
59
- assert_in_delta(0, method.self_time, 0.05)
60
- assert_in_delta(0, method.wait_time, 0.05)
61
- assert_in_delta(0.33, method.children_time, 0.05)
62
50
 
63
51
  method = methods[1]
64
52
  assert_equal('FiberTest#enumerator_with_fibers', method.full_name)
65
53
  assert_equal(1, method.called)
66
- assert_in_delta(0.33, method.total_time, 0.05)
67
- assert_in_delta(0, method.self_time, 0.05)
68
- assert_in_delta(0, method.wait_time, 0.05)
69
- assert_in_delta(0.33, method.children_time, 0.05)
70
54
 
71
55
  method = methods[2]
72
56
  assert_equal('Enumerator#next', method.full_name)
73
- assert_equal(3, method.called)
74
- assert_in_delta(0.22, method.total_time, 0.05)
75
- assert_in_delta(0, method.self_time, 0.05)
76
- assert_in_delta(0.22, method.wait_time, 0.05)
77
- assert_in_delta(0, method.children_time, 0.05)
57
+ assert_equal(2, method.called)
78
58
 
79
59
  method = methods[3]
80
- assert_equal('Kernel#sleep', method.full_name)
81
- assert_equal(1, method.called)
82
- assert_in_delta(0.11, method.total_time, 0.05)
83
- assert_in_delta(0.11, method.self_time, 0.05)
84
- assert_in_delta(0, method.wait_time, 0.05)
85
- assert_in_delta(0, method.children_time, 0.05)
86
-
87
- # Since these methods have such short times their order is a bit indeterminate
88
- method = methods.detect {|a_method| a_method.full_name == 'Class#new'}
89
60
  assert_equal('Class#new', method.full_name)
90
61
  assert_equal(1, method.called)
91
- assert_in_delta(0, method.total_time, 0.05)
92
- assert_in_delta(0, method.self_time, 0.05)
93
- assert_in_delta(0, method.wait_time, 0.05)
94
- assert_in_delta(0, method.children_time, 0.05)
95
-
96
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
97
- method = methods.detect {|a_method| a_method.full_name == 'Set#<<'}
98
- assert_equal('Set#<<', method.full_name)
99
- assert_equal(1, method.called)
100
- assert_in_delta(0, method.total_time, 0.05)
101
- assert_in_delta(0, method.self_time, 0.05)
102
- assert_in_delta(0, method.wait_time, 0.05)
103
- assert_in_delta(0, method.children_time, 0.05)
104
- end
105
62
 
106
- method = methods.detect {|a_method| a_method.full_name == 'Module#==='}
107
- assert_equal('Module#===', method.full_name)
63
+ method = methods[4]
64
+ assert_equal('Enumerator#initialize', method.full_name)
108
65
  assert_equal(1, method.called)
109
- assert_in_delta(0, method.total_time, 0.05)
110
- assert_in_delta(0, method.self_time, 0.05)
111
- assert_in_delta(0, method.wait_time, 0.05)
112
- assert_in_delta(0, method.children_time, 0.05)
113
66
 
114
- method = methods.detect {|a_method| a_method.full_name == 'Kernel#object_id'}
115
- assert_equal('Kernel#object_id', method.full_name)
116
- assert_equal(1, method.called)
117
- assert_in_delta(0, method.total_time, 0.05)
118
- assert_in_delta(0, method.self_time, 0.05)
119
- assert_in_delta(0, method.wait_time, 0.05)
120
- assert_in_delta(0, method.children_time, 0.05)
67
+ thread2 = result.threads[1]
68
+ methods = thread2.methods.sort.reverse
69
+ assert_equal(4, methods.count)
121
70
 
122
- method = methods.detect {|a_method| a_method.full_name == '<Class::Fiber>#current'}
123
- assert_equal('<Class::Fiber>#current', method.full_name)
71
+ method = methods[0]
72
+ assert_equal('Enumerator#each', method.full_name)
124
73
  assert_equal(1, method.called)
125
- assert_in_delta(0, method.total_time, 0.05)
126
- assert_in_delta(0, method.self_time, 0.05)
127
- assert_in_delta(0, method.wait_time, 0.05)
128
- assert_in_delta(0, method.children_time, 0.05)
129
74
 
130
- method = methods.detect {|a_method| a_method.full_name == 'Exception#exception'}
131
- assert_equal('Exception#exception', method.full_name)
75
+ method = methods[1]
76
+ assert_equal('Enumerator::Generator#each', method.full_name)
132
77
  assert_equal(1, method.called)
133
- assert_in_delta(0, method.total_time, 0.05)
134
- assert_in_delta(0, method.self_time, 0.05)
135
- assert_in_delta(0, method.wait_time, 0.05)
136
- assert_in_delta(0, method.children_time, 0.05)
137
78
 
138
- method = methods.detect {|a_method| a_method.full_name == 'Exception#backtrace'}
139
- assert_equal('Exception#backtrace', method.full_name)
79
+ method = methods[2]
80
+ assert_equal('Array#each', method.full_name)
140
81
  assert_equal(1, method.called)
141
- assert_in_delta(0, method.total_time, 0.05)
142
- assert_in_delta(0, method.self_time, 0.05)
143
- assert_in_delta(0, method.wait_time, 0.05)
144
- assert_in_delta(0, method.children_time, 0.05)
145
82
 
146
- method = methods.detect {|a_method| a_method.full_name == 'Enumerator#initialize'}
147
- assert_equal('Enumerator#initialize', method.full_name)
148
- assert_equal(1, method.called)
149
- assert_in_delta(0, method.total_time, 0.05)
150
- assert_in_delta(0, method.self_time, 0.05)
151
- assert_in_delta(0, method.wait_time, 0.05)
152
- assert_in_delta(0, method.children_time, 0.05)
83
+ method = methods[3]
84
+ assert_equal('Enumerator::Yielder#yield', method.full_name)
85
+ assert_equal(2, method.called)
86
+ end
153
87
 
154
- methods = result.threads[1].methods.sort.reverse
88
+ def test_fiber_resume
89
+ result = RubyProf.profile { fiber_yield_resume }
155
90
 
156
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6.0')
157
- assert_equal(10, methods.count)
158
- else
159
- assert_equal(11, methods.count)
160
- end
91
+ assert_equal(2, result.threads.size)
92
+
93
+ thread1 = result.threads[0]
94
+ methods = thread1.methods.sort.reverse
95
+ assert_equal(5, methods.count)
161
96
 
162
97
  method = methods[0]
163
- assert_equal('RubyProf::Profile#_inserted_parent_', method.full_name)
98
+ assert_equal('FiberTest#test_fiber_resume', method.full_name)
164
99
  assert_equal(1, method.called)
165
- assert_in_delta(0.33, method.total_time, 0.05)
166
- assert_in_delta(0, method.self_time, 0.05)
167
- assert_in_delta(0.11, method.wait_time, 0.05)
168
- assert_in_delta(0.22, method.children_time, 0.05)
169
100
 
170
101
  method = methods[1]
171
- assert_equal('Enumerator#each', method.full_name)
102
+ assert_equal('FiberTest#fiber_yield_resume', method.full_name)
172
103
  assert_equal(1, method.called)
173
- assert_in_delta(0.22, method.total_time, 0.05)
174
- assert_in_delta(0, method.self_time, 0.05)
175
- assert_in_delta(0, method.wait_time, 0.05)
176
- assert_in_delta(0.22, method.children_time, 0.05)
177
104
 
178
105
  method = methods[2]
179
- assert_equal('Enumerator::Generator#each', method.full_name)
180
- assert_equal(1, method.called)
181
- assert_in_delta(0.22, method.total_time, 0.05)
182
- assert_in_delta(0, method.self_time, 0.05)
183
- assert_in_delta(0, method.wait_time, 0.05)
184
- assert_in_delta(0.22, method.children_time, 0.05)
106
+ assert_equal('Fiber#resume', method.full_name)
107
+ assert_equal(2, method.called)
185
108
 
186
109
  method = methods[3]
187
- assert_equal('Array#each', method.full_name)
110
+ assert_equal('Class#new', method.full_name)
188
111
  assert_equal(1, method.called)
189
- assert_in_delta(0.22, method.total_time, 0.05)
190
- assert_in_delta(0, method.self_time, 0.05)
191
- assert_in_delta(0, method.wait_time, 0.05)
192
- assert_in_delta(0.22, method.children_time, 0.05)
193
112
 
194
113
  method = methods[4]
195
- assert_equal('Kernel#sleep', method.full_name)
196
- assert_equal(2, method.called)
197
- assert_in_delta(0.22, method.total_time, 0.05)
198
- assert_in_delta(0.22, method.self_time, 0.05)
199
- assert_in_delta(0, method.wait_time, 0.05)
200
- assert_in_delta(0, method.children_time, 0.05)
201
-
202
- # Since these methods have such short times their order is a bit indeterminate
203
- method = methods.detect {|a_method| a_method.full_name == 'Exception#initialize'}
204
- assert_equal('Exception#initialize', method.full_name)
114
+ assert_equal('Fiber#initialize', method.full_name)
205
115
  assert_equal(1, method.called)
206
- assert_in_delta(0, method.total_time, 0.05)
207
- assert_in_delta(0, method.self_time, 0.05)
208
- assert_in_delta(0, method.wait_time, 0.05)
209
- assert_in_delta(0, method.children_time, 0.05)
210
-
211
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
212
- method = methods.detect {|a_method| a_method.full_name == 'Set#<<'}
213
- assert_equal('Set#<<', method.full_name)
214
- assert_equal(2, method.called)
215
- assert_in_delta(0, method.total_time, 0.05)
216
- assert_in_delta(0, method.self_time, 0.05)
217
- assert_in_delta(0, method.wait_time, 0.05)
218
- assert_in_delta(0, method.children_time, 0.05)
219
- end
220
116
 
221
- method = methods.detect {|a_method| a_method.full_name == 'Kernel#object_id'}
222
- assert_equal('Kernel#object_id', method.full_name)
223
- assert_equal(2, method.called)
224
- assert_in_delta(0, method.total_time, 0.05)
225
- assert_in_delta(0, method.self_time, 0.05)
226
- assert_in_delta(0, method.wait_time, 0.05)
227
- assert_in_delta(0, method.children_time, 0.05)
117
+ thread1 = result.threads[1]
118
+ methods = thread1.methods.sort.reverse
119
+ assert_equal(2, methods.count)
228
120
 
229
- method = methods.detect {|a_method| a_method.full_name == 'Enumerator::Yielder#yield'}
230
- assert_equal('Enumerator::Yielder#yield', method.full_name)
231
- assert_equal(2, method.called)
232
- assert_in_delta(0, method.total_time, 0.05)
233
- assert_in_delta(0, method.self_time, 0.05)
234
- assert_in_delta(0, method.wait_time, 0.05)
235
- assert_in_delta(0, method.children_time, 0.05)
121
+ method = methods[0]
122
+ assert_equal('FiberTest#fiber_yield_resume', method.full_name)
123
+ assert_equal(1, method.called)
236
124
 
237
- method = methods.detect {|a_method| a_method.full_name == '<Class::Fiber>#current'}
238
- assert_equal('<Class::Fiber>#current', method.full_name)
125
+ method = methods[1]
126
+ assert_equal('<Class::Fiber>#yield', method.full_name)
239
127
  assert_equal(2, method.called)
240
- assert_in_delta(0, method.total_time, 0.05)
241
- assert_in_delta(0, method.self_time, 0.05)
242
- assert_in_delta(0, method.wait_time, 0.05)
243
- assert_in_delta(0, method.children_time, 0.05)
244
- end
245
-
246
- def test_merged_fibers
247
- result = RubyProf.profile(merge_fibers: true) { enumerator_with_fibers }
248
-
249
- assert_equal(1, result.threads.length)
250
-
251
- thread = result.threads.first
252
- assert_equal(thread.id, thread.fiber_id)
253
- assert_in_delta(0.3, thread.total_time, 0.05)
254
-
255
- assert(method_next = thread.methods.detect{|m| m.full_name == "Enumerator#next"})
256
- assert(method_each = thread.methods.detect{|m| m.full_name == "Enumerator#each"})
257
-
258
- assert_in_delta(0.2, method_next.total_time, 0.05)
259
- assert_in_delta(0.2, method_each.total_time, 0.05)
260
128
  end
261
129
  end
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'socket'
4
+ require 'fiber'
5
+
6
+ # The full implementation is given here, in order to show all the parts. A simpler implementation is given below.
7
+ class Reactor
8
+ def initialize
9
+ @readable = {}
10
+ @writable = {}
11
+ end
12
+
13
+ def run
14
+ while @readable.any? or @writable.any?
15
+ readable, writable = IO.select(@readable.keys, @writable.keys, [])
16
+
17
+ readable.each do |io|
18
+ @readable[io].resume
19
+ end
20
+
21
+ writable.each do |io|
22
+ @writable[io].resume
23
+ end
24
+ end
25
+ end
26
+
27
+ def wait_readable(io)
28
+ @readable[io] = Fiber.current
29
+ Fiber.yield
30
+ @readable.delete(io)
31
+
32
+ return yield if block_given?
33
+ end
34
+
35
+ def wait_writable(io)
36
+ @writable[io] = Fiber.current
37
+ Fiber.yield
38
+ @writable.delete(io)
39
+
40
+ return yield if block_given?
41
+ end
42
+ end
43
+
44
+ server = TCPServer.new('localhost', 9090)
45
+ reactor = Reactor.new
46
+
47
+ Fiber.new do
48
+ loop do
49
+ client = reactor.wait_readable(server) do
50
+ server.accept
51
+ end
52
+
53
+ Fiber.new do
54
+ while buffer = reactor.wait_readable(client) {client.gets}
55
+ reactor.wait_writable(client)
56
+ client.puts(buffer)
57
+ end
58
+
59
+ client.close
60
+ end.resume
61
+ end
62
+ end.resume
63
+
64
+ reactor.run
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-prof
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda, Charlie Savage, Roger Pack, Stefan Kaes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-19 00:00:00.000000000 Z
11
+ date: 2020-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -100,6 +100,7 @@ files:
100
100
  - ext/ruby_prof/ruby_prof.h
101
101
  - ext/ruby_prof/vc/ruby_prof.sln
102
102
  - ext/ruby_prof/vc/ruby_prof.vcxproj
103
+ - ext/ruby_prof/vc/ruby_prof_linux.vcxproj
103
104
  - lib/ruby-prof.rb
104
105
  - lib/ruby-prof/assets/call_stack_printer.html.erb
105
106
  - lib/ruby-prof/assets/call_stack_printer.png
@@ -131,6 +132,7 @@ files:
131
132
  - test/basic_test.rb
132
133
  - test/call_tree_visitor_test.rb
133
134
  - test/call_trees_test.rb
135
+ - test/client.rb
134
136
  - test/duplicate_names_test.rb
135
137
  - test/dynamic_method_test.rb
136
138
  - test/enumerable_test.rb
@@ -163,6 +165,7 @@ files:
163
165
  - test/printing_recursive_graph_test.rb
164
166
  - test/rack_test.rb
165
167
  - test/recursive_test.rb
168
+ - test/server.rb
166
169
  - test/singleton_test.rb
167
170
  - test/stack_printer_test.rb
168
171
  - test/start_stop_test.rb
@@ -177,7 +180,7 @@ metadata:
177
180
  bug_tracker_uri: https://github.com/ruby-prof/ruby-prof/issues
178
181
  changelog_uri: https://github.com/ruby-prof/ruby-prof/blob/master/CHANGES
179
182
  documentation_uri: https://ruby-prof.github.io/
180
- source_code_uri: https://github.com/ruby-prof/ruby-prof/tree/v1.3.2
183
+ source_code_uri: https://github.com/ruby-prof/ruby-prof/tree/v1.4.0
181
184
  post_install_message:
182
185
  rdoc_options: []
183
186
  require_paths: