ruby-prof 0.15.9 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- 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()
|