rbtrace 0.3.3 → 0.3.4
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/Gemfile.lock +1 -1
- data/README.md +6 -0
- data/bin/rbtrace +56 -10
- data/ext/extconf.rb +11 -9
- data/ext/rbtrace.c +99 -53
- data/rbtrace.gemspec +1 -1
- data/server.rb +1 -0
- data/test.sh +11 -1
- metadata +4 -4
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -29,6 +29,10 @@ rbtrace has several different tracing modes:
|
|
29
29
|
|
30
30
|
% rbtrace -p <PID> --methods "Kernel#sleep" "Proc#call"
|
31
31
|
|
32
|
+
### gc: trace garbage collections
|
33
|
+
|
34
|
+
% rbtrace -p <PID> --gc
|
35
|
+
|
32
36
|
## predefined tracers
|
33
37
|
|
34
38
|
rbtrace also includes a set of [predefined tracers](https://github.com/tmm1/rbtrace/tree/master/tracers)
|
@@ -182,7 +186,9 @@ for popular ruby libraries and functions.
|
|
182
186
|
|
183
187
|
## todo
|
184
188
|
|
189
|
+
* allow slow tracing of specific methods (--slow + --methods)
|
185
190
|
* add triggers to start tracing slow methods only inside another method
|
191
|
+
* add watch expressions to fire tracers only when an expression is true
|
186
192
|
* syntax check expressions before adding them
|
187
193
|
* add special expressions for method args (_arg0_, _arguments_)
|
188
194
|
* optimize local variable lookup to avoid instance_eval
|
data/bin/rbtrace
CHANGED
@@ -22,7 +22,7 @@ module MsgQ
|
|
22
22
|
ffi_lib 'c'
|
23
23
|
|
24
24
|
class EventMsg < FFI::Struct
|
25
|
-
BUF_SIZE = RUBY_PLATFORM =~ /linux/ ? 256 :
|
25
|
+
BUF_SIZE = RUBY_PLATFORM =~ /linux/ ? 256 : 120
|
26
26
|
IPC_NOWAIT = 004000
|
27
27
|
|
28
28
|
layout :mtype, :long,
|
@@ -159,7 +159,7 @@ class RBTracer
|
|
159
159
|
:arglist => false
|
160
160
|
}
|
161
161
|
}
|
162
|
-
@max_nesting = @nesting = 0
|
162
|
+
@max_nesting = @last_nesting = @nesting = 0
|
163
163
|
@last_tracer = nil
|
164
164
|
|
165
165
|
@out = STDOUT
|
@@ -167,6 +167,7 @@ class RBTracer
|
|
167
167
|
|
168
168
|
@show_time = false
|
169
169
|
@show_duration = true
|
170
|
+
@watch_slow = false
|
170
171
|
|
171
172
|
attach
|
172
173
|
end
|
@@ -177,6 +178,7 @@ class RBTracer
|
|
177
178
|
#
|
178
179
|
# Returns nothing.
|
179
180
|
def watch(msec)
|
181
|
+
@watch_slow = true
|
180
182
|
send_cmd(:watch, msec)
|
181
183
|
end
|
182
184
|
|
@@ -187,6 +189,13 @@ class RBTracer
|
|
187
189
|
send_cmd(:firehose)
|
188
190
|
end
|
189
191
|
|
192
|
+
# Turn on GC tracing.
|
193
|
+
#
|
194
|
+
# Returns nothing.
|
195
|
+
def gc
|
196
|
+
send_cmd(:gc)
|
197
|
+
end
|
198
|
+
|
190
199
|
# Add tracers for the given list of methods.
|
191
200
|
#
|
192
201
|
# methods - The String or Array of method selectors to trace.
|
@@ -342,9 +351,9 @@ class RBTracer
|
|
342
351
|
|
343
352
|
case event
|
344
353
|
when 'attached'
|
345
|
-
tracer_pid = *cmd
|
354
|
+
tracer_pid, = *cmd
|
346
355
|
if tracer_pid != Process.pid
|
347
|
-
STDERR.puts "*** process #{pid} is already being traced"
|
356
|
+
STDERR.puts "*** process #{pid} is already being traced (#{tracer_pid} != #{Process.pid})"
|
348
357
|
exit!(-1)
|
349
358
|
end
|
350
359
|
|
@@ -352,7 +361,7 @@ class RBTracer
|
|
352
361
|
return
|
353
362
|
|
354
363
|
when 'detached'
|
355
|
-
tracer_pid = *cmd
|
364
|
+
tracer_pid, = *cmd
|
356
365
|
if tracer_pid != Process.pid
|
357
366
|
STDERR.puts "*** process #{pid} detached #{tracer_pid}, but we are #{Process.pid}"
|
358
367
|
else
|
@@ -435,6 +444,7 @@ class RBTracer
|
|
435
444
|
|
436
445
|
@nesting += 1
|
437
446
|
@max_nesting = @nesting if @nesting > @max_nesting
|
447
|
+
@last_nesting = @nesting
|
438
448
|
@last_tracer = tracer
|
439
449
|
tracer[:last] = name
|
440
450
|
|
@@ -467,14 +477,21 @@ class RBTracer
|
|
467
477
|
end
|
468
478
|
|
469
479
|
tracer[:arglist] = false
|
480
|
+
@last_nesting = @nesting
|
470
481
|
|
471
482
|
when 'slow', 'cslow'
|
472
|
-
diff, nesting, mid, is_singleton, klass = *cmd
|
483
|
+
time, diff, nesting, mid, is_singleton, klass = *cmd
|
473
484
|
|
474
485
|
klass = @klasses[klass]
|
475
486
|
name = klass ? "#{klass}#{ is_singleton ? '.' : '#' }" : ''
|
476
487
|
name += @methods[mid] || '(unknown)'
|
477
488
|
|
489
|
+
if @show_time
|
490
|
+
t = Time.at(time/1_000_000)
|
491
|
+
print t.strftime("%H:%M:%S.")
|
492
|
+
print "%06d " % (time - t.to_f*1_000_000).round
|
493
|
+
end
|
494
|
+
|
478
495
|
print @prefix*nesting if nesting > 0
|
479
496
|
print name
|
480
497
|
if @show_duration
|
@@ -484,8 +501,23 @@ class RBTracer
|
|
484
501
|
puts
|
485
502
|
puts if nesting == 0
|
486
503
|
|
504
|
+
@last_nesting = nesting
|
505
|
+
|
506
|
+
when 'gc'
|
507
|
+
time, = *cmd
|
508
|
+
|
509
|
+
puts unless @watch_slow
|
510
|
+
if @show_time
|
511
|
+
t = Time.at(time/1_000_000)
|
512
|
+
print t.strftime("%H:%M:%S.")
|
513
|
+
print "%06d " % (time - t.to_f*1_000_000).round
|
514
|
+
end
|
515
|
+
print @prefix*@last_nesting if @last_nesting > 0
|
516
|
+
print "garbage_collect"
|
517
|
+
puts if @watch_slow
|
518
|
+
|
487
519
|
else
|
488
|
-
puts "unknown event: #{
|
520
|
+
puts "unknown event #{event}: #{cmd.inspect}"
|
489
521
|
|
490
522
|
end
|
491
523
|
rescue => e
|
@@ -500,7 +532,7 @@ class RBTracer
|
|
500
532
|
parser = Trollop::Parser.new do
|
501
533
|
version <<-EOS
|
502
534
|
rbtrace: like strace, but for ruby code
|
503
|
-
version 0.3.
|
535
|
+
version 0.3.4
|
504
536
|
(c) 2011 Aman Gupta (tmm1)
|
505
537
|
http://github.com/tmm1/rbtrace
|
506
538
|
EOS
|
@@ -525,6 +557,7 @@ Tracers:
|
|
525
557
|
rbtrace --firehose # trace all method calls
|
526
558
|
rbtrace --slow=250 # trace method calls slower than 250ms
|
527
559
|
rbtrace --methods a b c # trace calls to given methods
|
560
|
+
rbtrace --gc # trace garbage collections
|
528
561
|
|
529
562
|
rbtrace -c io # trace common input/output functions
|
530
563
|
rbtrace -c eventmachine # trace common eventmachine functions
|
@@ -569,6 +602,9 @@ EOS
|
|
569
602
|
:type => :strings,
|
570
603
|
:short => '-m'
|
571
604
|
|
605
|
+
opt :gc,
|
606
|
+
"trace garbage collections"
|
607
|
+
|
572
608
|
opt :start_time,
|
573
609
|
"show start time for each method call",
|
574
610
|
:short => '-t'
|
@@ -605,11 +641,17 @@ EOS
|
|
605
641
|
|
606
642
|
if out = opts[:output]
|
607
643
|
output = File.open(out, opts[:append] ? 'a+' : 'w')
|
644
|
+
output.sync = true
|
608
645
|
end
|
609
646
|
|
610
647
|
slow = nil
|
611
648
|
firehose = nil
|
612
649
|
methods = nil
|
650
|
+
gc = nil
|
651
|
+
|
652
|
+
if opts[:gc_given]
|
653
|
+
gc = true
|
654
|
+
end
|
613
655
|
|
614
656
|
if opts[:slow_given]
|
615
657
|
slow = opts[:slow]
|
@@ -642,8 +684,8 @@ EOS
|
|
642
684
|
end
|
643
685
|
end
|
644
686
|
|
645
|
-
|
646
|
-
$stderr.puts "Error: --slow, --firehose, --methods or --config required."
|
687
|
+
elsif !gc
|
688
|
+
$stderr.puts "Error: --slow, --gc, --firehose, --methods or --config required."
|
647
689
|
$stderr.puts "Try --help for help."
|
648
690
|
exit(-1)
|
649
691
|
end
|
@@ -655,6 +697,10 @@ EOS
|
|
655
697
|
parser.die :pid, "(#{e.message})"
|
656
698
|
end
|
657
699
|
|
700
|
+
if gc
|
701
|
+
tracer.gc
|
702
|
+
end
|
703
|
+
|
658
704
|
if slow
|
659
705
|
tracer.watch(slow)
|
660
706
|
elsif firehose
|
data/ext/extconf.rb
CHANGED
@@ -11,18 +11,20 @@ end
|
|
11
11
|
require 'mkmf'
|
12
12
|
require 'fileutils'
|
13
13
|
|
14
|
-
|
14
|
+
unless File.exists?("#{CWD}/dst/lib/libmsgpackc.a")
|
15
|
+
Logging.message "Building msgpack\n"
|
15
16
|
|
16
|
-
msgpack = File.basename('msgpack-0.5.4.tar.gz')
|
17
|
-
dir = File.basename(msgpack, '.tar.gz')
|
17
|
+
msgpack = File.basename('msgpack-0.5.4.tar.gz')
|
18
|
+
dir = File.basename(msgpack, '.tar.gz')
|
18
19
|
|
19
|
-
Dir.chdir('src') do
|
20
|
-
|
20
|
+
Dir.chdir('src') do
|
21
|
+
FileUtils.rm_rf(dir) if File.exists?(dir)
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
sys("tar zxvf #{msgpack}")
|
24
|
+
Dir.chdir(dir) do
|
25
|
+
sys("./configure --disable-shared --with-pic --prefix=#{CWD}/dst/")
|
26
|
+
sys("make install")
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
data/ext/rbtrace.c
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#include <assert.h>
|
1
2
|
#include <inttypes.h>
|
2
3
|
#include <errno.h>
|
3
4
|
#include <signal.h>
|
@@ -51,7 +52,7 @@ timeofday_usec()
|
|
51
52
|
#define MAX_TRACERS 100 // max method tracers
|
52
53
|
#define MAX_EXPRS 10 // max expressions per tracer
|
53
54
|
#ifndef BUF_SIZE // msgq buffer size
|
54
|
-
#define BUF_SIZE
|
55
|
+
#define BUF_SIZE 120
|
55
56
|
#endif
|
56
57
|
|
57
58
|
typedef struct {
|
@@ -79,6 +80,7 @@ static struct {
|
|
79
80
|
|
80
81
|
bool installed;
|
81
82
|
|
83
|
+
bool gc;
|
82
84
|
bool firehose;
|
83
85
|
|
84
86
|
bool slow;
|
@@ -105,6 +107,7 @@ rbtracer = {
|
|
105
107
|
|
106
108
|
.installed = false,
|
107
109
|
|
110
|
+
.gc = false,
|
108
111
|
.firehose = false,
|
109
112
|
|
110
113
|
.slow = false,
|
@@ -124,7 +127,7 @@ rbtracer = {
|
|
124
127
|
};
|
125
128
|
|
126
129
|
static inline void
|
127
|
-
|
130
|
+
rbtrace__send_event(int nargs, const char *name, ...)
|
128
131
|
{
|
129
132
|
if (!rbtracer.attached_pid ||
|
130
133
|
!rbtracer.sbuf ||
|
@@ -144,8 +147,10 @@ SEND_EVENT(int nargs, char *name, ...)
|
|
144
147
|
|
145
148
|
if (nargs > 0) {
|
146
149
|
int type;
|
147
|
-
|
150
|
+
|
148
151
|
int sint;
|
152
|
+
uint32_t uint;
|
153
|
+
uint64_t uint64;
|
149
154
|
unsigned long ulong;
|
150
155
|
char *str;
|
151
156
|
|
@@ -156,6 +161,11 @@ SEND_EVENT(int nargs, char *name, ...)
|
|
156
161
|
type = va_arg(ap, int);
|
157
162
|
switch (type) {
|
158
163
|
case 't':
|
164
|
+
uint64 = va_arg(ap, uint64_t);
|
165
|
+
msgpack_pack_uint64(pk, uint64);
|
166
|
+
break;
|
167
|
+
|
168
|
+
case 'n':
|
159
169
|
msgpack_pack_uint64(pk, timeofday_usec());
|
160
170
|
break;
|
161
171
|
|
@@ -184,14 +194,14 @@ SEND_EVENT(int nargs, char *name, ...)
|
|
184
194
|
case 's':
|
185
195
|
str = va_arg(ap, char *);
|
186
196
|
if (!str)
|
187
|
-
str = "";
|
197
|
+
str = (char *)"";
|
188
198
|
|
189
199
|
msgpack_pack_raw(pk, strlen(str));
|
190
200
|
msgpack_pack_raw_body(pk, str, strlen(str));
|
191
201
|
break;
|
192
202
|
|
193
203
|
default:
|
194
|
-
fprintf(stderr, "unknown type (%c) passed to
|
204
|
+
fprintf(stderr, "unknown type (%c) passed to rbtrace__send_event\n", (char)type);
|
195
205
|
}
|
196
206
|
}
|
197
207
|
|
@@ -202,7 +212,7 @@ SEND_EVENT(int nargs, char *name, ...)
|
|
202
212
|
msg.mtype = 1;
|
203
213
|
|
204
214
|
if (rbtracer.sbuf->size > sizeof(msg.buf)) {
|
205
|
-
fprintf(stderr, "
|
215
|
+
fprintf(stderr, "rbtrace__send_event(): message is too large (%zd > %lu)\n", rbtracer.sbuf->size, sizeof(msg.buf));
|
206
216
|
return;
|
207
217
|
}
|
208
218
|
|
@@ -222,14 +232,14 @@ SEND_EVENT(int nargs, char *name, ...)
|
|
222
232
|
}
|
223
233
|
|
224
234
|
static inline void
|
225
|
-
|
235
|
+
rbtrace__send_names(ID mid, VALUE klass)
|
226
236
|
{
|
227
237
|
if (!rbtracer.mid_tbl)
|
228
238
|
rbtracer.mid_tbl = st_init_numtable();
|
229
239
|
|
230
240
|
if (!st_is_member(rbtracer.mid_tbl, mid)) {
|
231
241
|
st_insert(rbtracer.mid_tbl, (st_data_t)mid, (st_data_t)1);
|
232
|
-
|
242
|
+
rbtrace__send_event(2,
|
233
243
|
"mid",
|
234
244
|
'l', mid,
|
235
245
|
's', rb_id2name(mid)
|
@@ -241,7 +251,7 @@ SEND_NAMES(ID mid, VALUE klass)
|
|
241
251
|
|
242
252
|
if (!st_is_member(rbtracer.klass_tbl, klass)) {
|
243
253
|
st_insert(rbtracer.klass_tbl, (st_data_t)klass, (st_data_t)1);
|
244
|
-
|
254
|
+
rbtrace__send_event(2,
|
245
255
|
"klass",
|
246
256
|
'l', klass,
|
247
257
|
's', rb_class2name(klass)
|
@@ -249,6 +259,37 @@ SEND_NAMES(ID mid, VALUE klass)
|
|
249
259
|
}
|
250
260
|
}
|
251
261
|
|
262
|
+
static void
|
263
|
+
rbtracer__resolve_query(char *query, VALUE *klass, VALUE *self, ID *mid)
|
264
|
+
{
|
265
|
+
char *idx = NULL, *method = NULL;
|
266
|
+
|
267
|
+
assert(klass && self && mid);
|
268
|
+
*klass = *self = *mid = 0;
|
269
|
+
|
270
|
+
if (NULL != (idx = rindex(query, '.'))) {
|
271
|
+
*idx = 0;
|
272
|
+
*self = rb_eval_string_protect(query, 0);
|
273
|
+
*idx = '.';
|
274
|
+
|
275
|
+
method = idx+1;
|
276
|
+
} else if (NULL != (idx = rindex(query, '#'))) {
|
277
|
+
*idx = 0;
|
278
|
+
*klass = rb_eval_string_protect(query, 0);
|
279
|
+
*idx = '#';
|
280
|
+
|
281
|
+
method = idx+1;
|
282
|
+
} else {
|
283
|
+
method = query;
|
284
|
+
}
|
285
|
+
|
286
|
+
if (method && *method) {
|
287
|
+
*mid = rb_intern(method);
|
288
|
+
}
|
289
|
+
}
|
290
|
+
|
291
|
+
static int in_event_hook = 0;
|
292
|
+
|
252
293
|
static void
|
253
294
|
#ifdef RUBY_VM
|
254
295
|
event_hook(rb_event_flag_t event, VALUE data, VALUE self, ID mid, VALUE klass)
|
@@ -256,8 +297,6 @@ event_hook(rb_event_flag_t event, VALUE data, VALUE self, ID mid, VALUE klass)
|
|
256
297
|
event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
257
298
|
#endif
|
258
299
|
{
|
259
|
-
static int in_event_hook = 0;
|
260
|
-
|
261
300
|
// do not re-enter this function
|
262
301
|
// after this, must `goto out` instead of `return`
|
263
302
|
if (in_event_hook) return;
|
@@ -266,8 +305,8 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
266
305
|
// skip allocators
|
267
306
|
if (mid == ID_ALLOCATOR) goto out;
|
268
307
|
|
269
|
-
// some serious 1.9.2 hax
|
270
308
|
#ifdef RUBY_VM
|
309
|
+
// some serious 1.9.2 hax
|
271
310
|
if (mid == 0 && ruby_current_thread) {
|
272
311
|
ID _mid;
|
273
312
|
VALUE _klass;
|
@@ -312,9 +351,10 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
312
351
|
}
|
313
352
|
|
314
353
|
if (diff > rbtracer.threshold * 1e3) {
|
315
|
-
|
316
|
-
|
354
|
+
rbtrace__send_names(mid, singleton ? self : klass);
|
355
|
+
rbtrace__send_event(6,
|
317
356
|
event == RUBY_EVENT_RETURN ? "slow" : "cslow",
|
357
|
+
't', rbtracer.call_times[ rbtracer.num_calls ],
|
318
358
|
'u', diff,
|
319
359
|
'u', rbtracer.num_calls,
|
320
360
|
'l', mid,
|
@@ -334,13 +374,15 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
334
374
|
if (rbtracer.num == 0) goto out;
|
335
375
|
|
336
376
|
for (i=0, n=0; i<MAX_TRACERS && n<rbtracer.num; i++) {
|
337
|
-
|
377
|
+
rbtracer_t *curr = &rbtracer.list[i];
|
378
|
+
|
379
|
+
if (curr->query) {
|
338
380
|
n++;
|
339
381
|
|
340
|
-
if (!
|
341
|
-
if (!
|
342
|
-
if (!
|
343
|
-
tracer =
|
382
|
+
if (!curr->mid || curr->mid == mid) {
|
383
|
+
if (!curr->klass || curr->klass == klass) {
|
384
|
+
if (!curr->self || curr->self == self) {
|
385
|
+
tracer = curr;
|
344
386
|
break;
|
345
387
|
}
|
346
388
|
}
|
@@ -355,10 +397,10 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
355
397
|
switch (event) {
|
356
398
|
case RUBY_EVENT_CALL:
|
357
399
|
case RUBY_EVENT_C_CALL:
|
358
|
-
|
359
|
-
|
400
|
+
rbtrace__send_names(mid, singleton ? self : klass);
|
401
|
+
rbtrace__send_event(5,
|
360
402
|
event == RUBY_EVENT_CALL ? "call" : "ccall",
|
361
|
-
'
|
403
|
+
'n',
|
362
404
|
'd', tracer ? tracer->id : 255, // hax
|
363
405
|
'l', mid,
|
364
406
|
'b', singleton,
|
@@ -394,7 +436,7 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
394
436
|
}
|
395
437
|
|
396
438
|
if (result && *result) {
|
397
|
-
|
439
|
+
rbtrace__send_event(3,
|
398
440
|
"exprval",
|
399
441
|
'd', tracer->id,
|
400
442
|
'd', i,
|
@@ -407,9 +449,9 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
407
449
|
|
408
450
|
case RUBY_EVENT_RETURN:
|
409
451
|
case RUBY_EVENT_C_RETURN:
|
410
|
-
|
452
|
+
rbtrace__send_event(2,
|
411
453
|
event == RUBY_EVENT_RETURN ? "return" : "creturn",
|
412
|
-
'
|
454
|
+
'n',
|
413
455
|
'd', tracer ? tracer->id : 255 // hax
|
414
456
|
);
|
415
457
|
break;
|
@@ -486,7 +528,7 @@ rbtracer_remove(char *query, int id)
|
|
486
528
|
}
|
487
529
|
|
488
530
|
out:
|
489
|
-
|
531
|
+
rbtrace__send_event(2,
|
490
532
|
"remove",
|
491
533
|
'd', tracer_id,
|
492
534
|
's', query
|
@@ -499,6 +541,7 @@ rbtracer_remove_all()
|
|
499
541
|
{
|
500
542
|
rbtracer.firehose = false;
|
501
543
|
rbtracer.slow = false;
|
544
|
+
rbtracer.gc = false;
|
502
545
|
|
503
546
|
int i;
|
504
547
|
for (i=0; i<MAX_TRACERS; i++) {
|
@@ -534,34 +577,13 @@ rbtracer_add(char *query)
|
|
534
577
|
}
|
535
578
|
if (!tracer) goto out;
|
536
579
|
|
537
|
-
char *idx, *method;
|
538
580
|
VALUE klass = 0, self = 0;
|
539
581
|
ID mid = 0;
|
540
582
|
|
541
|
-
|
542
|
-
*idx = 0;
|
543
|
-
self = rb_eval_string_protect(query, 0);
|
544
|
-
*idx = '.';
|
583
|
+
rbtracer__resolve_query(query, &klass, &self, &mid);
|
545
584
|
|
546
|
-
|
547
|
-
} else if (NULL != (idx = rindex(query, '#'))) {
|
548
|
-
*idx = 0;
|
549
|
-
klass = rb_eval_string_protect(query, 0);
|
550
|
-
*idx = '#';
|
551
|
-
|
552
|
-
method = idx+1;
|
553
|
-
} else {
|
554
|
-
method = query;
|
555
|
-
}
|
556
|
-
|
557
|
-
if (method && *method) {
|
558
|
-
mid = rb_intern(method);
|
559
|
-
if (!mid) goto out;
|
560
|
-
} else if (klass || self) {
|
561
|
-
mid = 0;
|
562
|
-
} else {
|
585
|
+
if (!mid && !klass && !self)
|
563
586
|
goto out;
|
564
|
-
}
|
565
587
|
|
566
588
|
memset(tracer, 0, sizeof(*tracer));
|
567
589
|
|
@@ -578,7 +600,7 @@ rbtracer_add(char *query)
|
|
578
600
|
rbtracer.num++;
|
579
601
|
|
580
602
|
out:
|
581
|
-
|
603
|
+
rbtrace__send_event(2,
|
582
604
|
"add",
|
583
605
|
'd', tracer_id,
|
584
606
|
's', query
|
@@ -606,7 +628,7 @@ rbtracer_add_expr(int id, char *expr)
|
|
606
628
|
}
|
607
629
|
|
608
630
|
out:
|
609
|
-
|
631
|
+
rbtrace__send_event(3,
|
610
632
|
"newexpr",
|
611
633
|
'd', tracer_id,
|
612
634
|
'd', expr_id,
|
@@ -719,6 +741,10 @@ sigurg(int signal)
|
|
719
741
|
if (!success || cmd.type != MSGPACK_OBJECT_ARRAY)
|
720
742
|
continue;
|
721
743
|
|
744
|
+
/* fprintf(stderr, "GOT: ");*/
|
745
|
+
/* msgpack_object_print(stderr, cmd);*/
|
746
|
+
/* fprintf(stderr, "\n");*/
|
747
|
+
|
722
748
|
ary = cmd.via.array;
|
723
749
|
|
724
750
|
if (ary.size < 1 ||
|
@@ -737,13 +763,13 @@ sigurg(int signal)
|
|
737
763
|
if (pid && rbtracer.attached_pid == 0)
|
738
764
|
rbtracer.attached_pid = pid;
|
739
765
|
|
740
|
-
|
766
|
+
rbtrace__send_event(1,
|
741
767
|
"attached",
|
742
768
|
'u', (uint32_t) rbtracer.attached_pid
|
743
769
|
);
|
744
770
|
|
745
771
|
} else if (0 == strncmp("detach", str.ptr, str.size)) {
|
746
|
-
|
772
|
+
rbtrace__send_event(1,
|
747
773
|
"detached",
|
748
774
|
'u', (uint32_t) rbtracer.attached_pid
|
749
775
|
);
|
@@ -785,14 +811,34 @@ sigurg(int signal)
|
|
785
811
|
query[str.size] = 0;
|
786
812
|
rbtracer_add_expr(last_tracer_id, query);
|
787
813
|
|
814
|
+
} else if (0 == strncmp("gc", str.ptr, str.size)) {
|
815
|
+
rbtracer.gc = true;
|
816
|
+
|
788
817
|
}
|
789
818
|
}
|
790
819
|
}
|
791
820
|
}
|
792
821
|
|
822
|
+
static void
|
823
|
+
rbtrace_gc_mark()
|
824
|
+
{
|
825
|
+
if (rbtracer.gc && !in_event_hook) {
|
826
|
+
rbtrace__send_event(1,
|
827
|
+
"gc",
|
828
|
+
'n'
|
829
|
+
);
|
830
|
+
}
|
831
|
+
}
|
832
|
+
|
833
|
+
static VALUE gc_hook;
|
834
|
+
|
793
835
|
void
|
794
836
|
Init_rbtrace()
|
795
837
|
{
|
838
|
+
// hook into the gc
|
839
|
+
gc_hook = Data_Wrap_Struct(rb_cObject, rbtrace_gc_mark, NULL, NULL);
|
840
|
+
rb_global_variable(&gc_hook);
|
841
|
+
|
796
842
|
// setup msgpack
|
797
843
|
rbtracer.sbuf = msgpack_sbuffer_new();
|
798
844
|
rbtracer.msgpacker = msgpack_packer_new(rbtracer.sbuf, msgpack_sbuffer_write);
|
data/rbtrace.gemspec
CHANGED
data/server.rb
CHANGED
data/test.sh
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
set -e
|
3
3
|
|
4
|
-
|
4
|
+
cd ext
|
5
|
+
[ -f Makefile ] && make clean
|
6
|
+
ruby extconf.rb
|
7
|
+
make
|
8
|
+
cd ..
|
9
|
+
|
10
|
+
bundle check
|
11
|
+
export RUBYOPT="-I."
|
12
|
+
|
5
13
|
ruby server.rb &
|
6
14
|
export PID=$!
|
7
15
|
|
@@ -26,6 +34,8 @@ trace -m sleep
|
|
26
34
|
trace -m sleep Dir.chdir Dir.pwd Process.pid "String#gsub" "String#*"
|
27
35
|
trace -m "Kernel#"
|
28
36
|
trace -m "String#gsub(self,@test)" "String#*(self,__source__)" "String#multiply_vowels(self,self.length,num)"
|
37
|
+
trace --gc --slow=200
|
38
|
+
trace --gc -m Dir.
|
29
39
|
trace --slow=250
|
30
40
|
trace --firehose
|
31
41
|
|
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: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 4
|
10
|
+
version: 0.3.4
|
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-02-
|
18
|
+
date: 2011-02-19 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|