rbtrace 0.3.16 → 0.3.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/bin/rbtrace +13 -8
  2. data/ext/rbtrace.c +33 -8
  3. data/rbtrace.gemspec +1 -1
  4. data/server.rb +10 -0
  5. data/test.sh +17 -14
  6. 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.16
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 + (uint64_t)tv.tv_usec;
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(), diff = 0;
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
- diff = usec - rbtracer.call_times[ rbtracer.num_calls ];
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, str.size)) {
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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rbtrace'
3
- s.version = '0.3.16'
3
+ s.version = '0.3.17'
4
4
  s.homepage = 'http://github.com/tmm1/rbtrace'
5
5
 
6
6
  s.authors = 'Aman Gupta'
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 2
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
- #trace -m Test.run --devmode
35
- #trace -m sleep
36
- #trace -m sleep Dir.chdir Dir.pwd Process.pid "String#gsub" "String#*"
37
- #trace -m "Kernel#"
38
- #trace -m "String#gsub(self,@test)" "String#*(self,__source__)" "String#multiply_vowels(self,self.length,num)"
39
- #trace --gc --slow=200
40
- #trace --gc -m Dir.
41
- #trace --slow=250
42
- #trace --slow=250 --slow-methods sleep
43
- #trace --gc -m Dir. --slow=250 --slow-methods sleep
44
- #trace --gc -m Dir. --slow=250
45
- #trace -m Process. Dir.pwd "Proc#call"
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: 51
4
+ hash: 49
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 16
10
- version: 0.3.16
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-25 00:00:00 -08:00
18
+ date: 2011-11-26 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency