rbtrace 0.3.16 → 0.3.17
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.
- data/bin/rbtrace +13 -8
- data/ext/rbtrace.c +33 -8
- data/rbtrace.gemspec +1 -1
- data/server.rb +10 -0
- data/test.sh +17 -14
- metadata +4 -4
data/bin/rbtrace
CHANGED
@@ -202,9 +202,9 @@ class RBTracer
|
|
202
202
|
# msec - The Fixnum threshold in milliseconds
|
203
203
|
#
|
204
204
|
# Returns nothing.
|
205
|
-
def watch(msec)
|
205
|
+
def watch(msec, cpu_only=false)
|
206
206
|
@watch_slow = true
|
207
|
-
send_cmd(:watch, msec)
|
207
|
+
send_cmd(cpu_only ? :watchcpu : :watch, msec)
|
208
208
|
end
|
209
209
|
|
210
210
|
# Turn on the firehose (show all method calls).
|
@@ -658,7 +658,7 @@ class RBTracer
|
|
658
658
|
parser = Trollop::Parser.new do
|
659
659
|
version <<-EOS
|
660
660
|
rbtrace: like strace, but for ruby code
|
661
|
-
version 0.3.
|
661
|
+
version 0.3.17
|
662
662
|
(c) 2011 Aman Gupta (tmm1)
|
663
663
|
http://github.com/tmm1/rbtrace
|
664
664
|
EOS
|
@@ -736,6 +736,11 @@ EOS
|
|
736
736
|
:default => 250,
|
737
737
|
:short => '-s'
|
738
738
|
|
739
|
+
opt :slowcpu,
|
740
|
+
"watch for method calls slower than 250 milliseconds (cpu time only)",
|
741
|
+
:default => 250,
|
742
|
+
:short => nil
|
743
|
+
|
739
744
|
opt :slow_methods,
|
740
745
|
"method(s) to restrict --slow to",
|
741
746
|
:type => :strings
|
@@ -810,8 +815,8 @@ EOS
|
|
810
815
|
ARGV.clear
|
811
816
|
end
|
812
817
|
|
813
|
-
unless %w[ fork eval slow firehose methods config gc ].find{ |n| opts[:"#{n}_given"] }
|
814
|
-
$stderr.puts "Error: --slow, --gc, --firehose, --methods or --config required."
|
818
|
+
unless %w[ fork eval slow slowcpu firehose methods config gc ].find{ |n| opts[:"#{n}_given"] }
|
819
|
+
$stderr.puts "Error: --slow, --slowcpu, --gc, --firehose, --methods or --config required."
|
815
820
|
$stderr.puts "Try --help for help."
|
816
821
|
exit(-1)
|
817
822
|
end
|
@@ -875,7 +880,7 @@ EOS
|
|
875
880
|
filtered.each_with_index do |line, i|
|
876
881
|
STDERR.puts " [#{(i+1).to_s.rjust(max_len)}] #{line.strip}"
|
877
882
|
end
|
878
|
-
STDERR.puts " [0] all #{filtered.size} processes"
|
883
|
+
STDERR.puts " [#{'0'.rjust(max_len)}] all #{filtered.size} processes"
|
879
884
|
|
880
885
|
while true
|
881
886
|
STDERR.sync = true
|
@@ -1007,8 +1012,8 @@ EOS
|
|
1007
1012
|
tracer.firehose
|
1008
1013
|
else
|
1009
1014
|
tracer.add(methods) if methods.any?
|
1010
|
-
if opts[:slow_given]
|
1011
|
-
tracer.watch(opts[:slow])
|
1015
|
+
if opts[:slow_given] || opts[:slowcpu_given]
|
1016
|
+
tracer.watch(opts[:slowcpu] || opts[:slow], opts[:slowcpu_given])
|
1012
1017
|
tracer.add_slow(smethods) if smethods.any?
|
1013
1018
|
end
|
1014
1019
|
end
|
data/ext/rbtrace.c
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
#include <strings.h>
|
12
12
|
#include <sys/ipc.h>
|
13
13
|
#include <sys/msg.h>
|
14
|
+
#include <sys/resource.h>
|
14
15
|
#include <sys/time.h>
|
15
16
|
#include <sys/types.h>
|
16
17
|
#include <sys/wait.h>
|
@@ -37,12 +38,22 @@
|
|
37
38
|
#define RSTRING_LEN(str) RSTRING(str)->len
|
38
39
|
#endif
|
39
40
|
|
41
|
+
static uint64_t
|
42
|
+
ru_utime_usec()
|
43
|
+
{
|
44
|
+
struct rusage r_usage;
|
45
|
+
getrusage(RUSAGE_SELF, &r_usage);
|
46
|
+
return (uint64_t)r_usage.ru_utime.tv_sec*1e6 +
|
47
|
+
(uint64_t)r_usage.ru_utime.tv_usec;
|
48
|
+
}
|
49
|
+
|
40
50
|
static uint64_t
|
41
51
|
timeofday_usec()
|
42
52
|
{
|
43
53
|
struct timeval tv;
|
44
54
|
gettimeofday(&tv, NULL);
|
45
|
-
return (uint64_t)tv.tv_sec*1e6 +
|
55
|
+
return (uint64_t)tv.tv_sec*1e6 +
|
56
|
+
(uint64_t)tv.tv_usec;
|
46
57
|
}
|
47
58
|
|
48
59
|
#define MAX_CALLS 32768 // up to this many stack frames examined in slow watch mode
|
@@ -87,7 +98,9 @@ static struct {
|
|
87
98
|
bool firehose;
|
88
99
|
|
89
100
|
bool slow;
|
101
|
+
bool slowcpu;
|
90
102
|
uint64_t call_times[MAX_CALLS];
|
103
|
+
uint64_t call_utimes[MAX_CALLS];
|
91
104
|
int num_calls;
|
92
105
|
uint32_t threshold;
|
93
106
|
|
@@ -116,6 +129,7 @@ rbtracer = {
|
|
116
129
|
.firehose = false,
|
117
130
|
|
118
131
|
.slow = false,
|
132
|
+
.slowcpu = false,
|
119
133
|
.num_calls = 0,
|
120
134
|
.threshold = 250,
|
121
135
|
|
@@ -377,13 +391,18 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
377
391
|
|
378
392
|
// are we watching for slow method calls?
|
379
393
|
if (rbtracer.slow && (!tracer || tracer->is_slow)) {
|
380
|
-
uint64_t usec = timeofday_usec(),
|
394
|
+
uint64_t usec = timeofday_usec(),
|
395
|
+
ut_usec = ru_utime_usec(),
|
396
|
+
diff = 0;
|
381
397
|
|
382
398
|
switch (event) {
|
383
399
|
case RUBY_EVENT_C_CALL:
|
384
400
|
case RUBY_EVENT_CALL:
|
385
|
-
if (rbtracer.num_calls < MAX_CALLS)
|
401
|
+
if (rbtracer.num_calls < MAX_CALLS) {
|
386
402
|
rbtracer.call_times[ rbtracer.num_calls ] = usec;
|
403
|
+
if (rbtracer.slowcpu)
|
404
|
+
rbtracer.call_utimes[ rbtracer.num_calls ] = ut_usec;
|
405
|
+
}
|
387
406
|
|
388
407
|
rbtracer.num_calls++;
|
389
408
|
break;
|
@@ -393,8 +412,12 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
393
412
|
if (rbtracer.num_calls > 0) {
|
394
413
|
rbtracer.num_calls--;
|
395
414
|
|
396
|
-
if (rbtracer.num_calls < MAX_CALLS)
|
397
|
-
|
415
|
+
if (rbtracer.num_calls < MAX_CALLS) {
|
416
|
+
if (rbtracer.slowcpu)
|
417
|
+
diff = ut_usec - rbtracer.call_utimes[ rbtracer.num_calls ];
|
418
|
+
else
|
419
|
+
diff = usec - rbtracer.call_times[ rbtracer.num_calls ];
|
420
|
+
}
|
398
421
|
}
|
399
422
|
break;
|
400
423
|
}
|
@@ -568,6 +591,7 @@ rbtracer_detach()
|
|
568
591
|
|
569
592
|
rbtracer.firehose = false;
|
570
593
|
rbtracer.slow = false;
|
594
|
+
rbtracer.slowcpu = false;
|
571
595
|
rbtracer.gc = false;
|
572
596
|
rbtracer.devmode = false;
|
573
597
|
|
@@ -724,13 +748,14 @@ out:
|
|
724
748
|
}
|
725
749
|
|
726
750
|
static void
|
727
|
-
rbtracer_watch(uint32_t threshold)
|
751
|
+
rbtracer_watch(uint32_t threshold, bool cpu_time)
|
728
752
|
{
|
729
753
|
if (!rbtracer.slow) {
|
730
754
|
rbtracer.num_calls = 0;
|
731
755
|
rbtracer.threshold = threshold;
|
732
756
|
rbtracer.firehose = false;
|
733
757
|
rbtracer.slow = true;
|
758
|
+
rbtracer.slowcpu = cpu_time;
|
734
759
|
|
735
760
|
event_hook_install();
|
736
761
|
}
|
@@ -837,13 +862,13 @@ rbtrace__process_event(msgpack_object cmd)
|
|
837
862
|
|
838
863
|
rbtracer_detach();
|
839
864
|
|
840
|
-
} else if (0 == strncmp("watch", str.ptr,
|
865
|
+
} else if (0 == strncmp("watch", str.ptr, 5)) {
|
841
866
|
if (ary.size != 2 ||
|
842
867
|
ary.ptr[1].type != MSGPACK_OBJECT_POSITIVE_INTEGER)
|
843
868
|
return;
|
844
869
|
|
845
870
|
unsigned int msec = ary.ptr[1].via.u64;
|
846
|
-
rbtracer_watch(msec);
|
871
|
+
rbtracer_watch(msec, str.size > 5 /* watchcpu */);
|
847
872
|
|
848
873
|
} else if (0 == strncmp("firehose", str.ptr, str.size)) {
|
849
874
|
rbtracer.firehose = true;
|
data/rbtrace.gemspec
CHANGED
data/server.rb
CHANGED
@@ -7,6 +7,14 @@ class String
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
+
def fib(n)
|
11
|
+
curr = 0
|
12
|
+
succ = 1
|
13
|
+
|
14
|
+
n.times{ curr, succ = succ, curr + succ }
|
15
|
+
curr
|
16
|
+
end
|
17
|
+
|
10
18
|
(reload_test = proc{
|
11
19
|
Object.send(:remove_const, :Test) if defined? Test
|
12
20
|
Test = Class.new do
|
@@ -29,6 +37,8 @@ while true
|
|
29
37
|
|
30
38
|
reload_test.call
|
31
39
|
Test.run
|
40
|
+
|
41
|
+
fib(1024*100)
|
32
42
|
end
|
33
43
|
}.call
|
34
44
|
end
|
data/test.sh
CHANGED
@@ -24,25 +24,28 @@ trace() {
|
|
24
24
|
echo ./bin/rbtrace -p $PID $*
|
25
25
|
echo ------------------------------------------
|
26
26
|
./bin/rbtrace -p $PID $* &
|
27
|
-
sleep
|
27
|
+
sleep 5
|
28
28
|
kill $!
|
29
29
|
wait $! || true
|
30
30
|
echo
|
31
31
|
}
|
32
32
|
|
33
|
-
bin/rbtrace -m sleep --wait 2 --exec ruby -e '10.times{ sleep 0.5 }'
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
#trace -m
|
38
|
-
#trace -m
|
39
|
-
#trace
|
40
|
-
#trace
|
41
|
-
#trace
|
42
|
-
#trace --
|
43
|
-
#trace --gc -m Dir.
|
44
|
-
#trace --
|
45
|
-
#trace -
|
33
|
+
# bin/rbtrace -m sleep --wait 2 --exec ruby -e '10.times{ sleep 0.5 }'
|
34
|
+
|
35
|
+
trace --slowcpu=500
|
36
|
+
|
37
|
+
# trace -m Test.run --devmode
|
38
|
+
# trace -m sleep
|
39
|
+
# trace -m sleep Dir.chdir Dir.pwd Process.pid "String#gsub" "String#*"
|
40
|
+
# trace -m "Kernel#"
|
41
|
+
# trace -m "String#gsub(self,@test)" "String#*(self,__source__)" "String#multiply_vowels(self,self.length,num)"
|
42
|
+
# trace --gc --slow=200
|
43
|
+
# trace --gc -m Dir.
|
44
|
+
# trace --slow=250
|
45
|
+
# trace --slow=250 --slow-methods sleep
|
46
|
+
# trace --gc -m Dir. --slow=250 --slow-methods sleep
|
47
|
+
# trace --gc -m Dir. --slow=250
|
48
|
+
# trace -m Process. Dir.pwd "Proc#call"
|
46
49
|
# trace --firehose
|
47
50
|
|
48
51
|
cleanup
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbtrace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 49
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 17
|
10
|
+
version: 0.3.17
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Aman Gupta
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-11-
|
18
|
+
date: 2011-11-26 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|