ruby-prof 0.15.9 → 0.16.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 +27 -1
- data/README.rdoc +83 -31
- data/bin/ruby-prof +4 -4
- data/doc/LICENSE.html +1 -1
- data/doc/README_rdoc.html +92 -33
- data/doc/Rack.html +1 -1
- data/doc/Rack/RubyProf.html +17 -14
- data/doc/RubyProf.html +30 -29
- data/doc/RubyProf/AbstractPrinter.html +1 -1
- data/doc/RubyProf/AggregateCallInfo.html +1 -1
- data/doc/RubyProf/CallInfo.html +1 -1
- data/doc/RubyProf/CallInfoPrinter.html +1 -1
- data/doc/RubyProf/CallInfoVisitor.html +1 -1
- data/doc/RubyProf/CallStackPrinter.html +1 -1
- data/doc/RubyProf/CallTreePrinter.html +349 -67
- data/doc/RubyProf/Cmd.html +5 -5
- data/doc/RubyProf/DotPrinter.html +2 -2
- data/doc/RubyProf/FlatPrinter.html +1 -1
- data/doc/RubyProf/FlatPrinterWithLineNumbers.html +1 -1
- data/doc/RubyProf/GraphHtmlPrinter.html +1 -1
- data/doc/RubyProf/GraphPrinter.html +1 -1
- data/doc/RubyProf/MethodInfo.html +2 -2
- data/doc/RubyProf/MultiPrinter.html +11 -9
- data/doc/RubyProf/Profile.html +94 -44
- data/doc/RubyProf/ProfileTask.html +1 -1
- data/doc/RubyProf/Thread.html +43 -1
- data/doc/created.rid +16 -16
- data/doc/examples/flat_txt.html +1 -1
- data/doc/examples/graph_html.html +1 -1
- data/doc/examples/graph_txt.html +3 -3
- data/doc/index.html +85 -30
- data/doc/js/navigation.js.gz +0 -0
- data/doc/js/search_index.js +1 -1
- data/doc/js/search_index.js.gz +0 -0
- data/doc/js/searcher.js +2 -2
- data/doc/js/searcher.js.gz +0 -0
- data/doc/table_of_contents.html +117 -68
- data/examples/cachegrind.out.1 +114 -0
- data/examples/cachegrind.out.1.32313213 +114 -0
- data/examples/graph.txt +1 -1
- data/ext/ruby_prof/extconf.rb +6 -2
- data/ext/ruby_prof/rp_measure_cpu_time.c +29 -31
- data/ext/ruby_prof/rp_method.c +1 -1
- data/ext/ruby_prof/rp_thread.c +57 -52
- data/ext/ruby_prof/ruby_prof.c +122 -66
- data/ext/ruby_prof/ruby_prof.h +2 -0
- data/lib/ruby-prof.rb +14 -13
- data/lib/ruby-prof/assets/call_stack_printer.js.html +1 -1
- data/lib/ruby-prof/compatibility.rb +9 -8
- data/lib/ruby-prof/method_info.rb +1 -1
- data/lib/ruby-prof/printers/call_tree_printer.rb +88 -50
- data/lib/ruby-prof/printers/dot_printer.rb +1 -1
- data/lib/ruby-prof/printers/multi_printer.rb +6 -4
- data/lib/ruby-prof/profile.rb +0 -1
- data/lib/ruby-prof/rack.rb +53 -16
- data/lib/ruby-prof/thread.rb +11 -0
- data/lib/ruby-prof/version.rb +1 -1
- data/test/exclude_threads_test.rb +2 -3
- data/test/fiber_test.rb +21 -7
- data/test/measure_cpu_time_test.rb +84 -24
- data/test/multi_printer_test.rb +5 -4
- data/test/pause_resume_test.rb +7 -7
- data/test/printers_test.rb +6 -4
- data/test/rack_test.rb +26 -1
- data/test/test_helper.rb +28 -3
- data/test/thread_test.rb +1 -0
- metadata +5 -3
@@ -0,0 +1,114 @@
|
|
1
|
+
events: wall_time
|
2
|
+
|
3
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
4
|
+
fn=Array#first
|
5
|
+
0 1
|
6
|
+
|
7
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
8
|
+
fn=Object#find_largest
|
9
|
+
31 3
|
10
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
11
|
+
cfn=Array#first
|
12
|
+
calls=1 32
|
13
|
+
32 1
|
14
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
15
|
+
cfn=Integer#upto
|
16
|
+
calls=1 36
|
17
|
+
36 11
|
18
|
+
|
19
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
20
|
+
fn=Integer#upto
|
21
|
+
0 2582
|
22
|
+
|
23
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
24
|
+
fn=Object#is_prime
|
25
|
+
16 92
|
26
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
27
|
+
cfn=Integer#upto
|
28
|
+
calls=200 18
|
29
|
+
18 2571
|
30
|
+
|
31
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
32
|
+
fn=Array#select
|
33
|
+
0 84
|
34
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
35
|
+
cfn=Object#is_prime
|
36
|
+
calls=200 26
|
37
|
+
26 2663
|
38
|
+
|
39
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
40
|
+
fn=Object#find_primes
|
41
|
+
24 2
|
42
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
43
|
+
cfn=Array#select
|
44
|
+
calls=1 25
|
45
|
+
25 2747
|
46
|
+
|
47
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
48
|
+
fn=Kernel#respond_to_missing?
|
49
|
+
0 30
|
50
|
+
|
51
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
52
|
+
fn=Kernel#rand
|
53
|
+
0 87
|
54
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
55
|
+
cfn=Kernel#respond_to_missing?
|
56
|
+
calls=200 10
|
57
|
+
10 30
|
58
|
+
|
59
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
60
|
+
fn=Array#each_index
|
61
|
+
0 70
|
62
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
63
|
+
cfn=Kernel#rand
|
64
|
+
calls=200 10
|
65
|
+
10 118
|
66
|
+
|
67
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
68
|
+
fn=Array#initialize
|
69
|
+
0 2
|
70
|
+
|
71
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
72
|
+
fn=Class#new
|
73
|
+
0 4
|
74
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
75
|
+
cfn=Array#initialize
|
76
|
+
calls=1 8
|
77
|
+
8 2
|
78
|
+
|
79
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
80
|
+
fn=Object#make_random_array
|
81
|
+
7 3
|
82
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
83
|
+
cfn=Class#new
|
84
|
+
calls=1 8
|
85
|
+
8 6
|
86
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
87
|
+
cfn=Array#each_index
|
88
|
+
calls=1 9
|
89
|
+
9 188
|
90
|
+
|
91
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
92
|
+
fn=Object#run_primes
|
93
|
+
45 2
|
94
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
95
|
+
cfn=Object#make_random_array
|
96
|
+
calls=1 47
|
97
|
+
47 197
|
98
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
99
|
+
cfn=Object#find_primes
|
100
|
+
calls=1 50
|
101
|
+
50 2749
|
102
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
103
|
+
cfn=Object#find_largest
|
104
|
+
calls=1 53
|
105
|
+
53 15
|
106
|
+
|
107
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/printers_test.rb
|
108
|
+
fn=PrintersTest#setup
|
109
|
+
14 5
|
110
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
111
|
+
cfn=Object#run_primes
|
112
|
+
calls=1 14
|
113
|
+
14 2963
|
114
|
+
|
@@ -0,0 +1,114 @@
|
|
1
|
+
events: wall_time
|
2
|
+
|
3
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
4
|
+
fn=Array#first
|
5
|
+
0 1
|
6
|
+
|
7
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
8
|
+
fn=Object#find_largest
|
9
|
+
31 3
|
10
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
11
|
+
cfn=Array#first
|
12
|
+
calls=1 32
|
13
|
+
32 1
|
14
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
15
|
+
cfn=Integer#upto
|
16
|
+
calls=1 36
|
17
|
+
36 11
|
18
|
+
|
19
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
20
|
+
fn=Integer#upto
|
21
|
+
0 2582
|
22
|
+
|
23
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
24
|
+
fn=Object#is_prime
|
25
|
+
16 92
|
26
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
27
|
+
cfn=Integer#upto
|
28
|
+
calls=200 18
|
29
|
+
18 2571
|
30
|
+
|
31
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
32
|
+
fn=Array#select
|
33
|
+
0 84
|
34
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
35
|
+
cfn=Object#is_prime
|
36
|
+
calls=200 26
|
37
|
+
26 2663
|
38
|
+
|
39
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
40
|
+
fn=Object#find_primes
|
41
|
+
24 2
|
42
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
43
|
+
cfn=Array#select
|
44
|
+
calls=1 25
|
45
|
+
25 2747
|
46
|
+
|
47
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
48
|
+
fn=Kernel#respond_to_missing?
|
49
|
+
0 30
|
50
|
+
|
51
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
52
|
+
fn=Kernel#rand
|
53
|
+
0 87
|
54
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
55
|
+
cfn=Kernel#respond_to_missing?
|
56
|
+
calls=200 10
|
57
|
+
10 30
|
58
|
+
|
59
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
60
|
+
fn=Array#each_index
|
61
|
+
0 70
|
62
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
63
|
+
cfn=Kernel#rand
|
64
|
+
calls=200 10
|
65
|
+
10 118
|
66
|
+
|
67
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
68
|
+
fn=Array#initialize
|
69
|
+
0 2
|
70
|
+
|
71
|
+
fl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
72
|
+
fn=Class#new
|
73
|
+
0 4
|
74
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
75
|
+
cfn=Array#initialize
|
76
|
+
calls=1 8
|
77
|
+
8 2
|
78
|
+
|
79
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
80
|
+
fn=Object#make_random_array
|
81
|
+
7 3
|
82
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
83
|
+
cfn=Class#new
|
84
|
+
calls=1 8
|
85
|
+
8 6
|
86
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/ruby_runtime
|
87
|
+
cfn=Array#each_index
|
88
|
+
calls=1 9
|
89
|
+
9 188
|
90
|
+
|
91
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
92
|
+
fn=Object#run_primes
|
93
|
+
45 2
|
94
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
95
|
+
cfn=Object#make_random_array
|
96
|
+
calls=1 47
|
97
|
+
47 197
|
98
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
99
|
+
cfn=Object#find_primes
|
100
|
+
calls=1 50
|
101
|
+
50 2749
|
102
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
103
|
+
cfn=Object#find_largest
|
104
|
+
calls=1 53
|
105
|
+
53 15
|
106
|
+
|
107
|
+
fl=/Users/stefan.kaes/src/ruby-prof/test/printers_test.rb
|
108
|
+
fn=PrintersTest#setup
|
109
|
+
14 5
|
110
|
+
cfl=/Users/stefan.kaes/src/ruby-prof/test/prime.rb
|
111
|
+
cfn=Object#run_primes
|
112
|
+
calls=1 14
|
113
|
+
14 2963
|
114
|
+
|
data/examples/graph.txt
CHANGED
@@ -98,7 +98,7 @@ The interpretation of method names is:
|
|
98
98
|
|
99
99
|
For example, we see that 97.74% of the time was spent in Object#is_prime and its
|
100
100
|
children. Of that time, almost everything was contributed by Integer#upto.
|
101
|
-
Overall,
|
101
|
+
Overall, Integer#upto was called 1001 times and 1000 of those calls were made
|
102
102
|
by Object#is_prime.
|
103
103
|
|
104
104
|
|
data/ext/ruby_prof/extconf.rb
CHANGED
@@ -38,7 +38,11 @@ def add_define(name, value = nil)
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
def windows?
|
42
|
+
RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
43
|
+
end
|
44
|
+
|
45
|
+
if !windows? && RUBY_PLATFORM !~ /(darwin|openbsd)/
|
42
46
|
$LDFLAGS += " -lrt" # for clock_gettime
|
43
47
|
end
|
44
48
|
add_define("RUBY_VERSION", RUBY_VERSION.gsub('.', ''))
|
@@ -51,7 +55,7 @@ if RUBY_VERSION > "1.9"
|
|
51
55
|
Thread.new{1}.join
|
52
56
|
set_trace_func nil
|
53
57
|
if threads.size < 2
|
54
|
-
# if we end up here, ruby does not automatically
|
58
|
+
# if we end up here, ruby does not automatically activate tracing in spawned threads
|
55
59
|
STDERR.puts("Ruby #{RUBY_VERSION} does not activate tracing in spawned threads. Consider upgrading.")
|
56
60
|
exit(1)
|
57
61
|
end
|
@@ -6,7 +6,34 @@
|
|
6
6
|
static VALUE cMeasureCpuTime;
|
7
7
|
|
8
8
|
/* The _WIN32 check is needed for msys (and maybe cygwin?) */
|
9
|
-
#if defined(
|
9
|
+
#if defined(_WIN32)
|
10
|
+
|
11
|
+
static unsigned long long get_cpu_time()
|
12
|
+
{
|
13
|
+
LARGE_INTEGER time;
|
14
|
+
QueryPerformanceCounter(&time);
|
15
|
+
return time.QuadPart;
|
16
|
+
}
|
17
|
+
|
18
|
+
static unsigned long long get_cpu_frequency()
|
19
|
+
{
|
20
|
+
static unsigned long long cpu_frequency;
|
21
|
+
|
22
|
+
if(!cpu_frequency) {
|
23
|
+
LARGE_INTEGER cpu_frequency_struct;
|
24
|
+
QueryPerformanceFrequency(&cpu_frequency_struct);
|
25
|
+
cpu_frequency = cpu_frequency_struct.QuadPart;
|
26
|
+
}
|
27
|
+
|
28
|
+
return cpu_frequency;
|
29
|
+
}
|
30
|
+
|
31
|
+
static double measure_cpu_time()
|
32
|
+
{
|
33
|
+
return ((double)get_cpu_time()) / get_cpu_frequency();
|
34
|
+
}
|
35
|
+
|
36
|
+
#else
|
10
37
|
|
11
38
|
#include <sys/resource.h>
|
12
39
|
#include <stdint.h>
|
@@ -52,8 +79,7 @@ static unsigned long long get_cpu_frequency()
|
|
52
79
|
return cpu_frequency;
|
53
80
|
}
|
54
81
|
|
55
|
-
static double
|
56
|
-
measure_cpu_time()
|
82
|
+
static double measure_cpu_time()
|
57
83
|
{
|
58
84
|
struct rusage rusage;
|
59
85
|
getrusage(RUSAGE_SELF, &rusage);
|
@@ -68,34 +94,6 @@ measure_cpu_time()
|
|
68
94
|
|
69
95
|
return seconds;
|
70
96
|
}
|
71
|
-
|
72
|
-
#elif defined(_WIN32)
|
73
|
-
|
74
|
-
static unsigned long long get_cpu_time()
|
75
|
-
{
|
76
|
-
LARGE_INTEGER time;
|
77
|
-
QueryPerformanceCounter(&time);
|
78
|
-
return time.QuadPart;
|
79
|
-
}
|
80
|
-
|
81
|
-
static unsigned long long get_cpu_frequency()
|
82
|
-
{
|
83
|
-
static unsigned long long cpu_frequency;
|
84
|
-
|
85
|
-
if(!cpu_frequency) {
|
86
|
-
LARGE_INTEGER cpu_frequency_struct;
|
87
|
-
QueryPerformanceFrequency(&cpu_frequency_struct);
|
88
|
-
cpu_frequency = cpu_frequency_struct.QuadPart;
|
89
|
-
}
|
90
|
-
|
91
|
-
return cpu_frequency;
|
92
|
-
}
|
93
|
-
|
94
|
-
static double
|
95
|
-
measure_cpu_time()
|
96
|
-
{
|
97
|
-
return ((double)get_cpu_time()) / get_cpu_frequency();
|
98
|
-
}
|
99
97
|
#endif
|
100
98
|
|
101
99
|
|
data/ext/ruby_prof/rp_method.c
CHANGED
@@ -286,7 +286,7 @@ One instance of the RubyProf::MethodInfo class is created per method
|
|
286
286
|
called per thread. Thus, if a method is called in two different
|
287
287
|
thread then there will be two RubyProf::MethodInfo objects
|
288
288
|
created. RubyProf::MethodInfo objects can be accessed via
|
289
|
-
the RubyProf::
|
289
|
+
the RubyProf::Profile object.
|
290
290
|
*/
|
291
291
|
|
292
292
|
/* call-seq:
|
data/ext/ruby_prof/rp_thread.c
CHANGED
@@ -12,41 +12,41 @@ thread_data_create()
|
|
12
12
|
thread_data_t* result = ALLOC(thread_data_t);
|
13
13
|
result->stack = prof_stack_create();
|
14
14
|
result->method_table = method_table_create();
|
15
|
-
|
16
|
-
|
15
|
+
result->object = Qnil;
|
16
|
+
result->methods = Qnil;
|
17
17
|
return result;
|
18
18
|
}
|
19
19
|
|
20
|
-
/* The underlying c structures are freed when the parent profile is freed.
|
20
|
+
/* The underlying c structures are freed when the parent profile is freed.
|
21
21
|
However, on shutdown the Ruby GC frees objects in any will-nilly order.
|
22
22
|
That means the ruby thread object wrapping the c thread struct may
|
23
23
|
be freed before the parent profile. Thus we add in a free function
|
24
|
-
for the garbage collector so that if it does get called will nil
|
24
|
+
for the garbage collector so that if it does get called will nil
|
25
25
|
out our Ruby object reference.*/
|
26
26
|
static void
|
27
27
|
thread_data_ruby_gc_free(thread_data_t* thread_data)
|
28
28
|
{
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
/* Has this thread object been accessed by Ruby? If
|
30
|
+
yes clean it up so to avoid a segmentation fault. */
|
31
|
+
if (thread_data->object != Qnil)
|
32
|
+
{
|
33
|
+
RDATA(thread_data->object)->data = NULL;
|
34
|
+
RDATA(thread_data->object)->dfree = NULL;
|
35
|
+
RDATA(thread_data->object)->dmark = NULL;
|
36
36
|
}
|
37
|
-
|
37
|
+
thread_data->object = Qnil;
|
38
38
|
}
|
39
39
|
|
40
40
|
static void
|
41
41
|
thread_data_free(thread_data_t* thread_data)
|
42
42
|
{
|
43
|
-
|
43
|
+
thread_data_ruby_gc_free(thread_data);
|
44
44
|
method_table_free(thread_data->method_table);
|
45
45
|
prof_stack_free(thread_data->stack);
|
46
46
|
|
47
47
|
thread_data->thread_id = Qnil;
|
48
48
|
|
49
|
-
|
49
|
+
xfree(thread_data);
|
50
50
|
}
|
51
51
|
|
52
52
|
static int
|
@@ -60,29 +60,28 @@ mark_methods(st_data_t key, st_data_t value, st_data_t result)
|
|
60
60
|
void
|
61
61
|
prof_thread_mark(thread_data_t *thread)
|
62
62
|
{
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
63
|
+
if (thread->object != Qnil)
|
64
|
+
rb_gc_mark(thread->object);
|
65
|
+
|
66
|
+
if (thread->methods != Qnil)
|
67
|
+
rb_gc_mark(thread->methods);
|
68
68
|
|
69
|
-
|
70
|
-
|
69
|
+
if (thread->thread_id != Qnil)
|
70
|
+
rb_gc_mark(thread->thread_id);
|
71
71
|
|
72
|
-
|
73
|
-
|
72
|
+
if (thread->fiber_id != Qnil)
|
73
|
+
rb_gc_mark(thread->fiber_id);
|
74
74
|
|
75
|
-
|
75
|
+
st_foreach(thread->method_table, mark_methods, 0);
|
76
76
|
}
|
77
77
|
|
78
78
|
VALUE
|
79
79
|
prof_thread_wrap(thread_data_t *thread)
|
80
80
|
{
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
return thread->object;
|
81
|
+
if (thread->object == Qnil) {
|
82
|
+
thread->object = Data_Wrap_Struct(cRpThread, prof_thread_mark, thread_data_ruby_gc_free, thread);
|
83
|
+
}
|
84
|
+
return thread->object;
|
86
85
|
}
|
87
86
|
|
88
87
|
static thread_data_t*
|
@@ -90,11 +89,11 @@ prof_get_thread(VALUE self)
|
|
90
89
|
{
|
91
90
|
/* Can't use Data_Get_Struct because that triggers the event hook
|
92
91
|
ending up in endless recursion. */
|
93
|
-
|
94
|
-
|
95
|
-
|
92
|
+
thread_data_t* result = DATA_PTR(self);
|
93
|
+
if (!result)
|
94
|
+
rb_raise(rb_eRuntimeError, "This RubyProf::Thread instance has already been freed, likely because its profile has been freed.");
|
96
95
|
|
97
|
-
|
96
|
+
return result;
|
98
97
|
}
|
99
98
|
|
100
99
|
/* ====== Thread Table ====== */
|
@@ -134,8 +133,12 @@ threads_table_lookup(prof_profile_t* profile, VALUE thread_id, VALUE fiber_id)
|
|
134
133
|
thread_data_t* result;
|
135
134
|
st_data_t val;
|
136
135
|
|
137
|
-
/*
|
138
|
-
|
136
|
+
/* If we should merge fibers, we use the thread_id as key, otherwise the fiber id.
|
137
|
+
None of this is perfect, as garbage collected fiber/thread might be reused again later.
|
138
|
+
A real solution would require integration with the garbage collector.
|
139
|
+
*/
|
140
|
+
VALUE key = profile->merge_fibers ? thread_id : fiber_id;
|
141
|
+
if (st_lookup(profile->threads_tbl, (st_data_t) key, &val))
|
139
142
|
{
|
140
143
|
result = (thread_data_t *) val;
|
141
144
|
}
|
@@ -143,10 +146,12 @@ threads_table_lookup(prof_profile_t* profile, VALUE thread_id, VALUE fiber_id)
|
|
143
146
|
{
|
144
147
|
result = thread_data_create();
|
145
148
|
result->thread_id = thread_id;
|
146
|
-
|
147
|
-
|
149
|
+
/* We set fiber id to 0 in the merge fiber case. Real fibers never have id 0,
|
150
|
+
so we can identify them later during printing.
|
151
|
+
*/
|
152
|
+
result->fiber_id = profile->merge_fibers ? INT2FIX(0) : fiber_id;
|
148
153
|
/* Insert the table */
|
149
|
-
threads_table_insert(profile,
|
154
|
+
threads_table_insert(profile, key, result);
|
150
155
|
}
|
151
156
|
return result;
|
152
157
|
}
|
@@ -183,24 +188,24 @@ switch_thread(void* prof, VALUE thread_id, VALUE fiber_id)
|
|
183
188
|
return thread_data;
|
184
189
|
}
|
185
190
|
|
186
|
-
int pause_thread(st_data_t key, st_data_t value, st_data_t data)
|
191
|
+
int pause_thread(st_data_t key, st_data_t value, st_data_t data)
|
187
192
|
{
|
188
193
|
thread_data_t* thread_data = (thread_data_t *) value;
|
189
|
-
|
194
|
+
prof_profile_t* profile = (prof_profile_t*)data;
|
190
195
|
|
191
196
|
prof_frame_t* frame = prof_stack_peek(thread_data->stack);
|
192
|
-
|
197
|
+
prof_frame_pause(frame, profile->measurement_at_pause_resume);
|
193
198
|
|
194
199
|
return ST_CONTINUE;
|
195
200
|
}
|
196
201
|
|
197
|
-
int unpause_thread(st_data_t key, st_data_t value, st_data_t data)
|
202
|
+
int unpause_thread(st_data_t key, st_data_t value, st_data_t data)
|
198
203
|
{
|
199
204
|
thread_data_t* thread_data = (thread_data_t *) value;
|
200
|
-
|
205
|
+
prof_profile_t* profile = (prof_profile_t*)data;
|
201
206
|
|
202
207
|
prof_frame_t* frame = prof_stack_peek(thread_data->stack);
|
203
|
-
|
208
|
+
prof_frame_unpause(frame, profile->measurement_at_pause_resume);
|
204
209
|
|
205
210
|
return ST_CONTINUE;
|
206
211
|
}
|
@@ -226,7 +231,7 @@ static VALUE
|
|
226
231
|
prof_thread_id(VALUE self)
|
227
232
|
{
|
228
233
|
thread_data_t* thread = prof_get_thread(self);
|
229
|
-
|
234
|
+
return thread->thread_id;
|
230
235
|
}
|
231
236
|
|
232
237
|
/* call-seq:
|
@@ -237,7 +242,7 @@ static VALUE
|
|
237
242
|
prof_fiber_id(VALUE self)
|
238
243
|
{
|
239
244
|
thread_data_t* thread = prof_get_thread(self);
|
240
|
-
|
245
|
+
return thread->fiber_id;
|
241
246
|
}
|
242
247
|
|
243
248
|
/* call-seq:
|
@@ -249,12 +254,12 @@ static VALUE
|
|
249
254
|
prof_thread_methods(VALUE self)
|
250
255
|
{
|
251
256
|
thread_data_t* thread = prof_get_thread(self);
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
257
|
+
if (thread->methods == Qnil)
|
258
|
+
{
|
259
|
+
thread->methods = rb_ary_new();
|
260
|
+
st_foreach(thread->method_table, collect_methods, thread->methods);
|
261
|
+
}
|
262
|
+
return thread->methods;
|
258
263
|
}
|
259
264
|
|
260
265
|
void rp_init_thread()
|