rbtrace 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|