ruby-prof 1.3.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +7 -0
- data/ext/ruby_prof/extconf.rb +0 -30
- data/ext/ruby_prof/rp_call_trees.c +2 -2
- data/ext/ruby_prof/rp_measure_allocations.c +1 -1
- data/ext/ruby_prof/rp_measure_process_time.c +1 -1
- data/ext/ruby_prof/rp_measure_wall_time.c +1 -1
- data/ext/ruby_prof/rp_profile.c +6 -23
- data/ext/ruby_prof/rp_profile.h +0 -1
- data/ext/ruby_prof/rp_stack.c +2 -2
- data/ext/ruby_prof/vc/ruby_prof.sln +8 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +14 -3
- data/ext/ruby_prof/vc/ruby_prof_linux.vcxproj +132 -0
- data/lib/ruby-prof/version.rb +1 -1
- data/test/client.rb +9 -0
- data/test/fiber_test.rb +55 -187
- data/test/server.rb +64 -0
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 756de796c2629622138d38034f1c895b2d2e32e8e00f1ef3d7b9bad2210b4cc2
|
|
4
|
+
data.tar.gz: 686d22e4138b8fbe4a03f9ba8bfcd1e5523671fb5b4a3f46029676339a2736b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz: '
|
|
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)
|
data/ext/ruby_prof/extconf.rb
CHANGED
|
@@ -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__)
|
data/ext/ruby_prof/rp_profile.c
CHANGED
|
@@ -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
|
-
|
|
86
|
-
VALUE fiber =
|
|
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 =
|
|
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,
|
|
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
|
}
|
data/ext/ruby_prof/rp_profile.h
CHANGED
data/ext/ruby_prof/rp_stack.c
CHANGED
|
@@ -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, "
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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>
|
data/lib/ruby-prof/version.rb
CHANGED
data/test/client.rb
ADDED
data/test/fiber_test.rb
CHANGED
|
@@ -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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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(
|
|
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
|
|
107
|
-
assert_equal('
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
assert_equal(
|
|
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
|
|
123
|
-
assert_equal('
|
|
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
|
|
131
|
-
assert_equal('
|
|
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
|
|
139
|
-
assert_equal('
|
|
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
|
|
147
|
-
assert_equal('Enumerator#
|
|
148
|
-
assert_equal(
|
|
149
|
-
|
|
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
|
-
|
|
88
|
+
def test_fiber_resume
|
|
89
|
+
result = RubyProf.profile { fiber_yield_resume }
|
|
155
90
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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('
|
|
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('
|
|
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('
|
|
180
|
-
assert_equal(
|
|
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('
|
|
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('
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
assert_equal(2,
|
|
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
|
|
230
|
-
assert_equal('
|
|
231
|
-
assert_equal(
|
|
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
|
|
238
|
-
assert_equal('<Class::Fiber>#
|
|
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
|
data/test/server.rb
ADDED
|
@@ -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.
|
|
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-
|
|
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.
|
|
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:
|