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.
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