memprof 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/memprof +16 -0
- data/ext/elf.c +31 -29
- data/ext/extconf.rb +11 -5
- data/ext/i386.h +2 -2
- data/ext/json.c +53 -0
- data/ext/json.h +48 -0
- data/ext/mach.c +442 -159
- data/ext/memprof.c +565 -459
- data/ext/mmap.h +73 -0
- data/ext/tracer.c +20 -2
- data/ext/tracer.h +14 -1
- data/ext/tracers/fd.c +204 -0
- data/ext/tracers/gc.c +79 -0
- data/ext/tracers/memcache.c +136 -0
- data/ext/tracers/memory.c +202 -0
- data/ext/tracers/mysql.c +82 -0
- data/ext/tracers/objects.c +160 -0
- data/ext/tramp.c +2 -2
- data/ext/util.c +22 -4
- data/ext/util.h +5 -0
- data/ext/x86_gen.c +3 -3
- data/ext/x86_gen.h +0 -13
- data/lib/memprof/tracer.rb +34 -0
- data/memprof.gemspec +1 -1
- data/spec/memprof_spec.rb +12 -4
- data/spec/tracing_spec.rb +135 -0
- metadata +14 -4
- data/ext/tracers/malloc.c +0 -163
data/ext/memprof.c
CHANGED
@@ -35,14 +35,6 @@ static st_table *objs = NULL;
|
|
35
35
|
/*
|
36
36
|
* stuff needed for heap dumping
|
37
37
|
*/
|
38
|
-
static double
|
39
|
-
rb_timeofday()
|
40
|
-
{
|
41
|
-
struct timeval tv;
|
42
|
-
gettimeofday(&tv, NULL);
|
43
|
-
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
|
44
|
-
}
|
45
|
-
|
46
38
|
static VALUE (*rb_classname)(VALUE);
|
47
39
|
static RUBY_DATA_FUNC *rb_bm_mark;
|
48
40
|
static RUBY_DATA_FUNC *rb_blk_free;
|
@@ -241,7 +233,6 @@ static VALUE
|
|
241
233
|
memprof_start(VALUE self)
|
242
234
|
{
|
243
235
|
if (!memprof_started) {
|
244
|
-
|
245
236
|
insert_tramp("rb_newobj", newobj_tramp);
|
246
237
|
insert_tramp("add_freelist", freelist_tramp);
|
247
238
|
memprof_started = 1;
|
@@ -329,6 +320,19 @@ memprof_stats_bang(int argc, VALUE *argv, VALUE self)
|
|
329
320
|
return Qnil;
|
330
321
|
}
|
331
322
|
|
323
|
+
static void
|
324
|
+
json_print(void *ctx, const char * str, unsigned int len)
|
325
|
+
{
|
326
|
+
FILE *out = (FILE *)ctx;
|
327
|
+
size_t written = 0;
|
328
|
+
while(1) {
|
329
|
+
written += fwrite(str + written, sizeof(char), len - written, out ? out : stdout);
|
330
|
+
if (written == len) break;
|
331
|
+
}
|
332
|
+
if (str && len > 0 && str[0] == '\n' && out)
|
333
|
+
fflush(out);
|
334
|
+
}
|
335
|
+
|
332
336
|
static VALUE
|
333
337
|
memprof_track(int argc, VALUE *argv, VALUE self)
|
334
338
|
{
|
@@ -342,22 +346,208 @@ memprof_track(int argc, VALUE *argv, VALUE self)
|
|
342
346
|
return Qnil;
|
343
347
|
}
|
344
348
|
|
349
|
+
static json_gen_config fancy_conf = { .beautify = 1, .indentString = " " };
|
350
|
+
static json_gen_config basic_conf = { .beautify = 0, .indentString = " " };
|
351
|
+
|
352
|
+
static json_gen
|
353
|
+
json_for_args(int argc, VALUE *argv)
|
354
|
+
{
|
355
|
+
FILE *out = NULL;
|
356
|
+
VALUE str;
|
357
|
+
rb_scan_args(argc, argv, "01", &str);
|
358
|
+
|
359
|
+
if (RTEST(str)) {
|
360
|
+
out = fopen(StringValueCStr(str), "w");
|
361
|
+
if (!out)
|
362
|
+
rb_raise(rb_eArgError, "unable to open output file");
|
363
|
+
}
|
364
|
+
|
365
|
+
if (!out)
|
366
|
+
out = stderr;
|
367
|
+
|
368
|
+
json_gen gen = json_gen_alloc2((json_print_t)&json_print, out == stderr ? &fancy_conf : &basic_conf, NULL, (void*)out);
|
369
|
+
|
370
|
+
return gen;
|
371
|
+
}
|
372
|
+
|
373
|
+
static void
|
374
|
+
json_free(json_gen gen)
|
375
|
+
{
|
376
|
+
FILE *out = (FILE*)gen->ctx;
|
377
|
+
if (out != stderr)
|
378
|
+
fclose(out);
|
379
|
+
json_gen_free(gen);
|
380
|
+
}
|
381
|
+
|
345
382
|
static VALUE
|
346
|
-
|
383
|
+
memprof_trace(int argc, VALUE *argv, VALUE self)
|
347
384
|
{
|
348
385
|
if (!rb_block_given_p())
|
349
386
|
rb_raise(rb_eArgError, "block required");
|
350
387
|
|
388
|
+
json_gen gen = json_for_args(argc, argv);
|
389
|
+
|
390
|
+
trace_set_output(gen);
|
391
|
+
json_gen_map_open(gen);
|
392
|
+
|
393
|
+
trace_invoke_all(TRACE_RESET);
|
351
394
|
trace_invoke_all(TRACE_START);
|
352
|
-
|
395
|
+
|
396
|
+
VALUE ret = rb_yield(Qnil);
|
397
|
+
|
353
398
|
trace_invoke_all(TRACE_DUMP);
|
354
399
|
trace_invoke_all(TRACE_STOP);
|
400
|
+
|
401
|
+
json_gen_map_close(gen);
|
402
|
+
json_gen_reset(gen);
|
403
|
+
|
404
|
+
json_free(gen);
|
405
|
+
trace_set_output(NULL);
|
406
|
+
|
407
|
+
return ret;
|
408
|
+
}
|
409
|
+
|
410
|
+
static int
|
411
|
+
each_request_entry(st_data_t key, st_data_t record, st_data_t arg)
|
412
|
+
{
|
413
|
+
json_gen gen = (json_gen)arg;
|
414
|
+
VALUE k = (VALUE)key;
|
415
|
+
VALUE v = (VALUE)record;
|
416
|
+
|
417
|
+
if (RTEST(v) && BUILTIN_TYPE(v) == T_STRING && RTEST(k) && BUILTIN_TYPE(k) == T_STRING &&
|
418
|
+
RSTRING_PTR(k)[0] >= 65 && RSTRING_PTR(k)[0] <= 90) {
|
419
|
+
json_gen_cstr(gen, StringValueCStr(k));
|
420
|
+
json_gen_cstr(gen, StringValueCStr(v));
|
421
|
+
}
|
422
|
+
|
423
|
+
return ST_CONTINUE;
|
424
|
+
}
|
425
|
+
|
426
|
+
static VALUE tracing_json_filename = Qnil;
|
427
|
+
static json_gen tracing_json_gen = NULL;
|
428
|
+
|
429
|
+
static VALUE
|
430
|
+
memprof_trace_filename_set(int argc, VALUE *argv, VALUE self)
|
431
|
+
{
|
432
|
+
if (tracing_json_gen) {
|
433
|
+
json_free(tracing_json_gen);
|
434
|
+
tracing_json_gen = NULL;
|
435
|
+
}
|
436
|
+
|
437
|
+
if (!RTEST(*argv)) {
|
438
|
+
tracing_json_filename = Qnil;
|
439
|
+
} else {
|
440
|
+
tracing_json_gen = json_for_args(argc, argv);
|
441
|
+
tracing_json_filename = *argv;
|
442
|
+
}
|
443
|
+
|
444
|
+
return tracing_json_filename;
|
445
|
+
}
|
446
|
+
|
447
|
+
static VALUE
|
448
|
+
memprof_trace_filename_get(VALUE self)
|
449
|
+
{
|
450
|
+
return tracing_json_filename;
|
451
|
+
}
|
452
|
+
|
453
|
+
static VALUE
|
454
|
+
memprof_trace_request(VALUE self, VALUE env)
|
455
|
+
{
|
456
|
+
if (!rb_block_given_p())
|
457
|
+
rb_raise(rb_eArgError, "block required");
|
458
|
+
|
459
|
+
double secs;
|
460
|
+
struct timeval now;
|
461
|
+
|
462
|
+
json_gen gen;
|
463
|
+
if (tracing_json_gen)
|
464
|
+
gen = tracing_json_gen;
|
465
|
+
else
|
466
|
+
gen = json_for_args(0, NULL);
|
467
|
+
|
468
|
+
json_gen_map_open(gen);
|
469
|
+
|
470
|
+
json_gen_cstr(gen, "start");
|
471
|
+
gettimeofday(&now, NULL);
|
472
|
+
json_gen_integer(gen, (now.tv_sec * 1000000) + now.tv_usec);
|
473
|
+
|
474
|
+
json_gen_cstr(gen, "tracers");
|
475
|
+
json_gen_map_open(gen);
|
476
|
+
|
477
|
+
trace_set_output(gen);
|
355
478
|
trace_invoke_all(TRACE_RESET);
|
356
|
-
|
479
|
+
trace_invoke_all(TRACE_START);
|
480
|
+
|
481
|
+
secs = timeofday();
|
482
|
+
VALUE ret = rb_yield(Qnil);
|
483
|
+
secs = timeofday() - secs;
|
484
|
+
|
485
|
+
trace_invoke_all(TRACE_DUMP);
|
486
|
+
trace_invoke_all(TRACE_STOP);
|
487
|
+
|
488
|
+
json_gen_map_close(gen);
|
489
|
+
|
490
|
+
if (RTEST(env) && BUILTIN_TYPE(env) == T_HASH) {
|
491
|
+
VALUE val, str;
|
492
|
+
val = rb_hash_aref(env, rb_str_new2("action_controller.request.path_parameters"));
|
493
|
+
if (!RTEST(val))
|
494
|
+
val = rb_hash_aref(env, rb_str_new2("action_dispatch.request.parameters"));
|
495
|
+
|
496
|
+
if (RTEST(val) && BUILTIN_TYPE(val) == T_HASH) {
|
497
|
+
json_gen_cstr(gen, "rails");
|
498
|
+
json_gen_map_open(gen);
|
499
|
+
str = rb_hash_aref(val, rb_str_new2("controller"));
|
500
|
+
if (RTEST(str) && BUILTIN_TYPE(str) == T_STRING) {
|
501
|
+
json_gen_cstr(gen, "controller");
|
502
|
+
json_gen_cstr(gen, RSTRING_PTR(str));
|
503
|
+
}
|
504
|
+
|
505
|
+
str = rb_hash_aref(val, rb_str_new2("action"));
|
506
|
+
if (RTEST(str) && BUILTIN_TYPE(str) == T_STRING) {
|
507
|
+
json_gen_cstr(gen, "action");
|
508
|
+
json_gen_cstr(gen, RSTRING_PTR(str));
|
509
|
+
}
|
510
|
+
json_gen_map_close(gen);
|
511
|
+
}
|
512
|
+
|
513
|
+
json_gen_cstr(gen, "request");
|
514
|
+
json_gen_map_open(gen);
|
515
|
+
// struct RHash *hash = RHASH(env);
|
516
|
+
// st_foreach(hash->tbl, each_request_entry, (st_data_t)gen);
|
517
|
+
|
518
|
+
#define DUMP_HASH_ENTRY(key) do { \
|
519
|
+
str = rb_hash_aref(env, rb_str_new2(key)); \
|
520
|
+
if (RTEST(str) && \
|
521
|
+
BUILTIN_TYPE(str) == T_STRING && \
|
522
|
+
RSTRING_PTR(str)) { \
|
523
|
+
json_gen_cstr(gen, key); \
|
524
|
+
json_gen_cstr(gen, RSTRING_PTR(str)); \
|
525
|
+
} \
|
526
|
+
} while(0)
|
527
|
+
// DUMP_HASH_ENTRY("HTTP_USER_AGENT");
|
528
|
+
DUMP_HASH_ENTRY("REQUEST_PATH");
|
529
|
+
DUMP_HASH_ENTRY("PATH_INFO");
|
530
|
+
DUMP_HASH_ENTRY("REMOTE_ADDR");
|
531
|
+
DUMP_HASH_ENTRY("REQUEST_URI");
|
532
|
+
DUMP_HASH_ENTRY("REQUEST_METHOD");
|
533
|
+
DUMP_HASH_ENTRY("QUERY_STRING");
|
534
|
+
|
535
|
+
json_gen_map_close(gen);
|
536
|
+
}
|
537
|
+
|
538
|
+
json_gen_cstr(gen, "time");
|
539
|
+
json_gen_double(gen, secs);
|
540
|
+
|
541
|
+
json_gen_map_close(gen);
|
542
|
+
json_gen_reset(gen);
|
543
|
+
|
544
|
+
if (gen != tracing_json_gen)
|
545
|
+
json_free(gen);
|
546
|
+
|
547
|
+
return ret;
|
357
548
|
}
|
358
549
|
|
359
|
-
#include
|
360
|
-
#include <stdarg.h>
|
550
|
+
#include "json.h"
|
361
551
|
#include "env.h"
|
362
552
|
#include "rubyio.h"
|
363
553
|
#include "re.h"
|
@@ -378,118 +568,46 @@ memprof_track_fun(int argc, VALUE *argv, VALUE self)
|
|
378
568
|
#define RSTRING_LEN(str) RSTRING(str)->len
|
379
569
|
#endif
|
380
570
|
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
typedef enum {
|
385
|
-
yajl_gen_start,
|
386
|
-
yajl_gen_map_start,
|
387
|
-
yajl_gen_map_key,
|
388
|
-
yajl_gen_map_val,
|
389
|
-
yajl_gen_array_start,
|
390
|
-
yajl_gen_in_array,
|
391
|
-
yajl_gen_complete,
|
392
|
-
yajl_gen_error
|
393
|
-
} yajl_gen_state;
|
394
|
-
|
395
|
-
struct yajl_gen_t
|
396
|
-
{
|
397
|
-
unsigned int depth;
|
398
|
-
unsigned int pretty;
|
399
|
-
const char * indentString;
|
400
|
-
yajl_gen_state state[YAJL_MAX_DEPTH];
|
401
|
-
yajl_print_t print;
|
402
|
-
void * ctx; /* yajl_buf */
|
403
|
-
/* memory allocation routines */
|
404
|
-
yajl_alloc_funcs alloc;
|
405
|
-
};
|
406
|
-
|
407
|
-
static void
|
408
|
-
yajl_gen_reset(yajl_gen gen)
|
409
|
-
{
|
410
|
-
yajl_gen_clear(gen);
|
411
|
-
assert (gen->state[gen->depth] == yajl_gen_complete);
|
412
|
-
gen->state[gen->depth] = yajl_gen_start;
|
413
|
-
gen->print(gen->ctx, "\n", 1);
|
414
|
-
}
|
415
|
-
|
416
|
-
/* END HAX
|
417
|
-
*/
|
418
|
-
|
419
|
-
static yajl_gen_status
|
420
|
-
yajl_gen_cstr(yajl_gen gen, const char * str)
|
421
|
-
{
|
422
|
-
if (!str || str[0] == 0)
|
423
|
-
return yajl_gen_null(gen);
|
424
|
-
else
|
425
|
-
return yajl_gen_string(gen, (unsigned char *)str, strlen(str));
|
426
|
-
}
|
427
|
-
|
428
|
-
static yajl_gen_status
|
429
|
-
yajl_gen_format(yajl_gen gen, char *format, ...)
|
430
|
-
{
|
431
|
-
va_list args;
|
432
|
-
char *str;
|
433
|
-
int bytes_printed = 0;
|
434
|
-
|
435
|
-
yajl_gen_status ret;
|
436
|
-
|
437
|
-
va_start(args, format);
|
438
|
-
bytes_printed = vasprintf(&str, format, args);
|
439
|
-
assert(bytes_printed != -1);
|
440
|
-
va_end(args);
|
441
|
-
|
442
|
-
ret = yajl_gen_string(gen, (unsigned char *)str, strlen(str));
|
443
|
-
free(str);
|
444
|
-
return ret;
|
445
|
-
}
|
446
|
-
|
447
|
-
static yajl_gen_status
|
448
|
-
yajl_gen_id(yajl_gen gen, ID id)
|
571
|
+
static json_gen_status
|
572
|
+
json_gen_id(json_gen gen, ID id)
|
449
573
|
{
|
450
574
|
if (id) {
|
451
575
|
if (id < 100)
|
452
|
-
return
|
576
|
+
return json_gen_format(gen, ":%c", id);
|
453
577
|
else
|
454
|
-
return
|
578
|
+
return json_gen_format(gen, ":%s", rb_id2name(id));
|
455
579
|
} else
|
456
|
-
return
|
457
|
-
}
|
458
|
-
|
459
|
-
static yajl_gen_status
|
460
|
-
yajl_gen_pointer(yajl_gen gen, void* ptr)
|
461
|
-
{
|
462
|
-
return yajl_gen_format(gen, "0x%x", ptr);
|
580
|
+
return json_gen_null(gen);
|
463
581
|
}
|
464
582
|
|
465
|
-
static
|
466
|
-
|
583
|
+
static json_gen_status
|
584
|
+
json_gen_value(json_gen gen, VALUE obj)
|
467
585
|
{
|
468
586
|
if (FIXNUM_P(obj))
|
469
|
-
return
|
587
|
+
return json_gen_integer(gen, NUM2LONG(obj));
|
470
588
|
else if (NIL_P(obj) || obj == Qundef)
|
471
|
-
return
|
589
|
+
return json_gen_null(gen);
|
472
590
|
else if (obj == Qtrue)
|
473
|
-
return
|
591
|
+
return json_gen_bool(gen, 1);
|
474
592
|
else if (obj == Qfalse)
|
475
|
-
return
|
593
|
+
return json_gen_bool(gen, 0);
|
476
594
|
else if (SYMBOL_P(obj))
|
477
|
-
return
|
595
|
+
return json_gen_id(gen, SYM2ID(obj));
|
478
596
|
else
|
479
|
-
return
|
597
|
+
return json_gen_pointer(gen, (void*)obj);
|
480
598
|
}
|
481
599
|
|
482
600
|
static int
|
483
601
|
each_hash_entry(st_data_t key, st_data_t record, st_data_t arg)
|
484
602
|
{
|
485
|
-
|
603
|
+
json_gen gen = (json_gen)arg;
|
486
604
|
VALUE k = (VALUE)key;
|
487
605
|
VALUE v = (VALUE)record;
|
488
606
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
607
|
+
json_gen_array_open(gen);
|
608
|
+
json_gen_value(gen, k);
|
609
|
+
json_gen_value(gen, v);
|
610
|
+
json_gen_array_close(gen);
|
493
611
|
|
494
612
|
return ST_CONTINUE;
|
495
613
|
}
|
@@ -497,13 +615,13 @@ each_hash_entry(st_data_t key, st_data_t record, st_data_t arg)
|
|
497
615
|
static int
|
498
616
|
each_ivar(st_data_t key, st_data_t record, st_data_t arg)
|
499
617
|
{
|
500
|
-
|
618
|
+
json_gen gen = (json_gen)arg;
|
501
619
|
ID id = (ID)key;
|
502
620
|
VALUE val = (VALUE)record;
|
503
621
|
const char *name = rb_id2name(id);
|
504
622
|
|
505
|
-
|
506
|
-
|
623
|
+
json_gen_cstr(gen, name ? name : "(none)");
|
624
|
+
json_gen_value(gen, val);
|
507
625
|
|
508
626
|
return ST_CONTINUE;
|
509
627
|
}
|
@@ -546,16 +664,16 @@ nd_type_str(VALUE obj)
|
|
546
664
|
}
|
547
665
|
|
548
666
|
static inline void
|
549
|
-
obj_dump_class(
|
667
|
+
obj_dump_class(json_gen gen, VALUE obj)
|
550
668
|
{
|
551
669
|
if (RBASIC(obj)->klass) {
|
552
|
-
|
553
|
-
|
670
|
+
json_gen_cstr(gen, "class");
|
671
|
+
json_gen_value(gen, RBASIC(obj)->klass);
|
554
672
|
|
555
673
|
VALUE name = rb_classname(RBASIC(obj)->klass);
|
556
674
|
if (RTEST(name)) {
|
557
|
-
|
558
|
-
|
675
|
+
json_gen_cstr(gen, "class_name");
|
676
|
+
json_gen_cstr(gen, RSTRING_PTR(name));
|
559
677
|
}
|
560
678
|
}
|
561
679
|
}
|
@@ -568,33 +686,33 @@ obj_dump_class(yajl_gen gen, VALUE obj)
|
|
568
686
|
*/
|
569
687
|
|
570
688
|
static void
|
571
|
-
obj_dump(VALUE obj,
|
689
|
+
obj_dump(VALUE obj, json_gen gen)
|
572
690
|
{
|
573
691
|
int type;
|
574
|
-
|
692
|
+
json_gen_map_open(gen);
|
575
693
|
|
576
|
-
|
577
|
-
|
694
|
+
json_gen_cstr(gen, "_id");
|
695
|
+
json_gen_value(gen, obj);
|
578
696
|
|
579
697
|
struct obj_track *tracker = NULL;
|
580
698
|
if (st_lookup(objs, (st_data_t)obj, (st_data_t *)&tracker) && BUILTIN_TYPE(obj) != T_NODE) {
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
699
|
+
json_gen_cstr(gen, "file");
|
700
|
+
json_gen_cstr(gen, tracker->source);
|
701
|
+
json_gen_cstr(gen, "line");
|
702
|
+
json_gen_integer(gen, tracker->line);
|
703
|
+
json_gen_cstr(gen, "time");
|
704
|
+
json_gen_integer(gen, (tracker->time[0].tv_sec * 1000000) + tracker->time[0].tv_usec);
|
587
705
|
}
|
588
706
|
|
589
|
-
|
707
|
+
json_gen_cstr(gen, "type");
|
590
708
|
switch (type=BUILTIN_TYPE(obj)) {
|
591
709
|
case T_DATA:
|
592
|
-
|
710
|
+
json_gen_cstr(gen, "data");
|
593
711
|
obj_dump_class(gen, obj);
|
594
712
|
|
595
713
|
if (DATA_PTR(obj)) {
|
596
|
-
|
597
|
-
|
714
|
+
json_gen_cstr(gen, "data");
|
715
|
+
json_gen_pointer(gen, DATA_PTR(obj));
|
598
716
|
}
|
599
717
|
|
600
718
|
if (RDATA(obj)->dfree == (RUBY_DATA_FUNC)rb_blk_free) {
|
@@ -603,73 +721,73 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
603
721
|
|
604
722
|
val = *(void**)(DATA_PTR(obj) + memprof_config.offset_BLOCK_body);
|
605
723
|
if (val) {
|
606
|
-
|
607
|
-
|
724
|
+
json_gen_cstr(gen, "nd_body");
|
725
|
+
json_gen_pointer(gen, val);
|
608
726
|
}
|
609
727
|
|
610
728
|
val = *(void**)(DATA_PTR(obj) + memprof_config.offset_BLOCK_var);
|
611
729
|
if (val) {
|
612
|
-
|
613
|
-
|
730
|
+
json_gen_cstr(gen, "nd_var");
|
731
|
+
json_gen_pointer(gen, val);
|
614
732
|
}
|
615
733
|
|
616
734
|
val = *(void**)(DATA_PTR(obj) + memprof_config.offset_BLOCK_cref);
|
617
735
|
if (val) {
|
618
|
-
|
619
|
-
|
736
|
+
json_gen_cstr(gen, "nd_cref");
|
737
|
+
json_gen_pointer(gen, val);
|
620
738
|
}
|
621
739
|
|
622
740
|
val = *(void**)(DATA_PTR(obj) + memprof_config.offset_BLOCK_dyna_vars);
|
623
741
|
if (val) {
|
624
|
-
|
625
|
-
|
742
|
+
json_gen_cstr(gen, "vars");
|
743
|
+
json_gen_pointer(gen, val);
|
626
744
|
}
|
627
745
|
|
628
746
|
val = *(void**)(DATA_PTR(obj) + memprof_config.offset_BLOCK_scope);
|
629
747
|
if (val) {
|
630
|
-
|
631
|
-
|
748
|
+
json_gen_cstr(gen, "scope");
|
749
|
+
json_gen_pointer(gen, val);
|
632
750
|
}
|
633
751
|
|
634
752
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_BLOCK_self);
|
635
|
-
|
636
|
-
|
753
|
+
json_gen_cstr(gen, "self");
|
754
|
+
json_gen_value(gen, ptr);
|
637
755
|
|
638
756
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_BLOCK_klass);
|
639
|
-
|
640
|
-
|
757
|
+
json_gen_cstr(gen, "klass");
|
758
|
+
json_gen_value(gen, ptr);
|
641
759
|
|
642
760
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_BLOCK_orig_thread);
|
643
|
-
|
644
|
-
|
761
|
+
json_gen_cstr(gen, "thread");
|
762
|
+
json_gen_value(gen, ptr);
|
645
763
|
|
646
764
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_BLOCK_wrapper);
|
647
765
|
if (RTEST(ptr)) {
|
648
|
-
|
649
|
-
|
766
|
+
json_gen_cstr(gen, "wrapper");
|
767
|
+
json_gen_value(gen, ptr);
|
650
768
|
}
|
651
769
|
|
652
770
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_BLOCK_block_obj);
|
653
771
|
if (RTEST(ptr)) {
|
654
|
-
|
655
|
-
|
772
|
+
json_gen_cstr(gen, "block");
|
773
|
+
json_gen_value(gen, ptr);
|
656
774
|
}
|
657
775
|
|
658
776
|
/* TODO: is .prev actually useful? refers to non-heap allocated struct BLOCKs,
|
659
777
|
* but we don't print out any information about those
|
660
778
|
*/
|
661
779
|
/*
|
662
|
-
|
663
|
-
|
780
|
+
json_gen_cstr(gen, "prev");
|
781
|
+
json_gen_array_open(gen);
|
664
782
|
val = *(void**)(DATA_PTR(obj) + memprof_config.offset_BLOCK_prev);
|
665
783
|
while (val) {
|
666
|
-
|
784
|
+
json_gen_pointer(gen, val);
|
667
785
|
prev = val;
|
668
786
|
val = *(void**)(ptr + memprof_config.offset_BLOCK_prev);
|
669
787
|
if (prev == val)
|
670
788
|
break;
|
671
789
|
}
|
672
|
-
|
790
|
+
json_gen_array_close(gen);
|
673
791
|
*/
|
674
792
|
|
675
793
|
} else if (RDATA(obj)->dmark == (RUBY_DATA_FUNC)rb_bm_mark) {
|
@@ -678,57 +796,57 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
678
796
|
|
679
797
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_METHOD_klass);
|
680
798
|
if (RTEST(ptr)) {
|
681
|
-
|
682
|
-
|
799
|
+
json_gen_cstr(gen, "klass");
|
800
|
+
json_gen_value(gen, ptr);
|
683
801
|
}
|
684
802
|
|
685
803
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_METHOD_rklass);
|
686
804
|
if (RTEST(ptr)) {
|
687
|
-
|
688
|
-
|
805
|
+
json_gen_cstr(gen, "rklass");
|
806
|
+
json_gen_value(gen, ptr);
|
689
807
|
}
|
690
808
|
|
691
809
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_METHOD_recv);
|
692
810
|
if (RTEST(ptr)) {
|
693
|
-
|
694
|
-
|
811
|
+
json_gen_cstr(gen, "recv");
|
812
|
+
json_gen_value(gen, ptr);
|
695
813
|
}
|
696
814
|
|
697
815
|
ptr = *(VALUE*)(DATA_PTR(obj) + memprof_config.offset_METHOD_body);
|
698
816
|
if (RTEST(ptr)) {
|
699
|
-
|
700
|
-
|
817
|
+
json_gen_cstr(gen, "node");
|
818
|
+
json_gen_value(gen, ptr);
|
701
819
|
}
|
702
820
|
|
703
821
|
mid = *(ID*)(DATA_PTR(obj) + memprof_config.offset_METHOD_id);
|
704
822
|
if (mid) {
|
705
|
-
|
706
|
-
|
823
|
+
json_gen_cstr(gen, "mid");
|
824
|
+
json_gen_id(gen, mid);
|
707
825
|
}
|
708
826
|
|
709
827
|
id = *(ID*)(DATA_PTR(obj) + memprof_config.offset_METHOD_oid);
|
710
828
|
if (id && id != mid) {
|
711
|
-
|
712
|
-
|
829
|
+
json_gen_cstr(gen, "oid");
|
830
|
+
json_gen_id(gen, id);
|
713
831
|
}
|
714
832
|
|
715
833
|
} else if (RDATA(obj)->dmark == (RUBY_DATA_FUNC)rb_thread_mark) {
|
716
834
|
rb_thread_t th = (rb_thread_t)DATA_PTR(obj);
|
717
835
|
|
718
836
|
if (th == rb_curr_thread) {
|
719
|
-
|
720
|
-
|
837
|
+
json_gen_cstr(gen, "current");
|
838
|
+
json_gen_bool(gen, 1);
|
721
839
|
} else {
|
722
840
|
if (th->dyna_vars) {
|
723
|
-
|
724
|
-
|
841
|
+
json_gen_cstr(gen, "varmap");
|
842
|
+
json_gen_pointer(gen, th->dyna_vars);
|
725
843
|
}
|
726
844
|
|
727
|
-
|
728
|
-
|
845
|
+
json_gen_cstr(gen, "node");
|
846
|
+
json_gen_pointer(gen, th->node);
|
729
847
|
|
730
|
-
|
731
|
-
|
848
|
+
json_gen_cstr(gen, "cref");
|
849
|
+
json_gen_pointer(gen, th->cref);
|
732
850
|
|
733
851
|
char *status;
|
734
852
|
switch (th->status) {
|
@@ -748,8 +866,8 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
748
866
|
status = "unknown";
|
749
867
|
}
|
750
868
|
|
751
|
-
|
752
|
-
|
869
|
+
json_gen_cstr(gen, "status");
|
870
|
+
json_gen_cstr(gen, status);
|
753
871
|
|
754
872
|
#define WAIT_FD (1<<0)
|
755
873
|
#define WAIT_SELECT (1<<1)
|
@@ -757,172 +875,172 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
757
875
|
#define WAIT_JOIN (1<<3)
|
758
876
|
#define WAIT_PID (1<<4)
|
759
877
|
|
760
|
-
|
761
|
-
|
878
|
+
json_gen_cstr(gen, "wait_for");
|
879
|
+
json_gen_array_open(gen);
|
762
880
|
if (th->wait_for & WAIT_FD)
|
763
|
-
|
881
|
+
json_gen_cstr(gen, "fd");
|
764
882
|
if (th->wait_for & WAIT_SELECT)
|
765
|
-
|
883
|
+
json_gen_cstr(gen, "select");
|
766
884
|
if (th->wait_for & WAIT_TIME)
|
767
|
-
|
885
|
+
json_gen_cstr(gen, "time");
|
768
886
|
if (th->wait_for & WAIT_JOIN)
|
769
|
-
|
887
|
+
json_gen_cstr(gen, "join");
|
770
888
|
if (th->wait_for & WAIT_PID)
|
771
|
-
|
772
|
-
|
889
|
+
json_gen_cstr(gen, "pid");
|
890
|
+
json_gen_array_close(gen);
|
773
891
|
|
774
892
|
if (th->wait_for & WAIT_FD) {
|
775
|
-
|
776
|
-
|
893
|
+
json_gen_cstr(gen, "fd");
|
894
|
+
json_gen_integer(gen, th->fd);
|
777
895
|
}
|
778
896
|
|
779
897
|
#define DELAY_INFTY 1E30
|
780
898
|
|
781
899
|
if (th->wait_for & WAIT_TIME) {
|
782
|
-
|
900
|
+
json_gen_cstr(gen, "delay");
|
783
901
|
if (th->delay == DELAY_INFTY)
|
784
|
-
|
902
|
+
json_gen_cstr(gen, "infinity");
|
785
903
|
else
|
786
|
-
|
904
|
+
json_gen_double(gen, th->delay - timeofday());
|
787
905
|
}
|
788
906
|
|
789
907
|
if (th->wait_for & WAIT_JOIN) {
|
790
|
-
|
791
|
-
|
908
|
+
json_gen_cstr(gen, "join");
|
909
|
+
json_gen_value(gen, th->join->thread);
|
792
910
|
}
|
793
911
|
}
|
794
912
|
|
795
|
-
|
796
|
-
|
913
|
+
json_gen_cstr(gen, "priority");
|
914
|
+
json_gen_integer(gen, th->priority);
|
797
915
|
|
798
916
|
if (th == rb_main_thread) {
|
799
|
-
|
800
|
-
|
917
|
+
json_gen_cstr(gen, "main");
|
918
|
+
json_gen_bool(gen, 1);
|
801
919
|
}
|
802
920
|
|
803
921
|
if (th->next && th->next != rb_main_thread) {
|
804
|
-
|
805
|
-
|
922
|
+
json_gen_cstr(gen, "next");
|
923
|
+
json_gen_value(gen, th->next->thread);
|
806
924
|
}
|
807
925
|
if (th->prev && th->prev != th && (th->prev == rb_main_thread || th->prev != th->next)) {
|
808
|
-
|
809
|
-
|
926
|
+
json_gen_cstr(gen, "prev");
|
927
|
+
json_gen_value(gen, th->prev->thread);
|
810
928
|
}
|
811
929
|
|
812
930
|
if (th->locals) {
|
813
|
-
|
814
|
-
|
931
|
+
json_gen_cstr(gen, "variables");
|
932
|
+
json_gen_map_open(gen);
|
815
933
|
st_foreach(th->locals, each_ivar, (st_data_t)gen);
|
816
|
-
|
934
|
+
json_gen_map_close(gen);
|
817
935
|
}
|
818
936
|
|
819
937
|
}
|
820
938
|
break;
|
821
939
|
|
822
940
|
case T_STRUCT:
|
823
|
-
|
941
|
+
json_gen_cstr(gen, "struct");
|
824
942
|
obj_dump_class(gen, obj);
|
825
943
|
break;
|
826
944
|
|
827
945
|
case T_FILE:
|
828
|
-
|
946
|
+
json_gen_cstr(gen, "file");
|
829
947
|
obj_dump_class(gen, obj);
|
830
948
|
|
831
949
|
OpenFile *file = RFILE(obj)->fptr;
|
832
950
|
|
833
951
|
if (file->f) {
|
834
|
-
|
835
|
-
|
952
|
+
json_gen_cstr(gen, "fileno");
|
953
|
+
json_gen_integer(gen, fileno(file->f));
|
836
954
|
}
|
837
955
|
|
838
956
|
if (file->f2) {
|
839
|
-
|
840
|
-
|
957
|
+
json_gen_cstr(gen, "fileno2");
|
958
|
+
json_gen_integer(gen, fileno(file->f2));
|
841
959
|
}
|
842
960
|
|
843
961
|
if (file->pid) {
|
844
|
-
|
845
|
-
|
962
|
+
json_gen_cstr(gen, "pid");
|
963
|
+
json_gen_integer(gen, file->pid);
|
846
964
|
}
|
847
965
|
|
848
966
|
if (file->path) {
|
849
|
-
|
850
|
-
|
967
|
+
json_gen_cstr(gen, "path");
|
968
|
+
json_gen_cstr(gen, file->path);
|
851
969
|
}
|
852
970
|
|
853
971
|
if (file->mode) {
|
854
|
-
|
855
|
-
|
972
|
+
json_gen_cstr(gen, "mode");
|
973
|
+
json_gen_array_open(gen);
|
856
974
|
if (file->mode & FMODE_READABLE)
|
857
|
-
|
975
|
+
json_gen_cstr(gen, "readable");
|
858
976
|
if (file->mode & FMODE_WRITABLE)
|
859
|
-
|
977
|
+
json_gen_cstr(gen, "writable");
|
860
978
|
if (file->mode & FMODE_READWRITE)
|
861
|
-
|
979
|
+
json_gen_cstr(gen, "readwrite");
|
862
980
|
if (file->mode & FMODE_APPEND)
|
863
|
-
|
981
|
+
json_gen_cstr(gen, "append");
|
864
982
|
if (file->mode & FMODE_CREATE)
|
865
|
-
|
983
|
+
json_gen_cstr(gen, "create");
|
866
984
|
if (file->mode & FMODE_BINMODE)
|
867
|
-
|
985
|
+
json_gen_cstr(gen, "binmode");
|
868
986
|
if (file->mode & FMODE_SYNC)
|
869
|
-
|
987
|
+
json_gen_cstr(gen, "sync");
|
870
988
|
if (file->mode & FMODE_WBUF)
|
871
|
-
|
989
|
+
json_gen_cstr(gen, "wbuf");
|
872
990
|
if (file->mode & FMODE_RBUF)
|
873
|
-
|
991
|
+
json_gen_cstr(gen, "rbuf");
|
874
992
|
if (file->mode & FMODE_WSPLIT)
|
875
|
-
|
993
|
+
json_gen_cstr(gen, "wsplit");
|
876
994
|
if (file->mode & FMODE_WSPLIT_INITIALIZED)
|
877
|
-
|
878
|
-
|
995
|
+
json_gen_cstr(gen, "wsplit_initialized");
|
996
|
+
json_gen_array_close(gen);
|
879
997
|
}
|
880
998
|
|
881
999
|
break;
|
882
1000
|
|
883
1001
|
case T_FLOAT:
|
884
|
-
|
1002
|
+
json_gen_cstr(gen, "float");
|
885
1003
|
obj_dump_class(gen, obj);
|
886
1004
|
|
887
|
-
|
888
|
-
|
1005
|
+
json_gen_cstr(gen, "data");
|
1006
|
+
json_gen_double(gen, RFLOAT(obj)->value);
|
889
1007
|
break;
|
890
1008
|
|
891
1009
|
case T_BIGNUM:
|
892
|
-
|
1010
|
+
json_gen_cstr(gen, "bignum");
|
893
1011
|
obj_dump_class(gen, obj);
|
894
1012
|
|
895
|
-
|
896
|
-
|
1013
|
+
json_gen_cstr(gen, "negative");
|
1014
|
+
json_gen_bool(gen, RBIGNUM(obj)->sign == 0);
|
897
1015
|
|
898
|
-
|
899
|
-
|
1016
|
+
json_gen_cstr(gen, "length");
|
1017
|
+
json_gen_integer(gen, RBIGNUM(obj)->len);
|
900
1018
|
|
901
|
-
|
902
|
-
|
1019
|
+
json_gen_cstr(gen, "data");
|
1020
|
+
json_gen_string(gen, RBIGNUM(obj)->digits, RBIGNUM(obj)->len);
|
903
1021
|
break;
|
904
1022
|
|
905
1023
|
case T_MATCH:
|
906
|
-
|
1024
|
+
json_gen_cstr(gen, "match");
|
907
1025
|
obj_dump_class(gen, obj);
|
908
1026
|
|
909
|
-
|
910
|
-
|
1027
|
+
json_gen_cstr(gen, "data");
|
1028
|
+
json_gen_value(gen, RMATCH(obj)->str);
|
911
1029
|
break;
|
912
1030
|
|
913
1031
|
case T_REGEXP:
|
914
|
-
|
1032
|
+
json_gen_cstr(gen, "regexp");
|
915
1033
|
obj_dump_class(gen, obj);
|
916
1034
|
|
917
|
-
|
918
|
-
|
1035
|
+
json_gen_cstr(gen, "length");
|
1036
|
+
json_gen_integer(gen, RREGEXP(obj)->len);
|
919
1037
|
|
920
|
-
|
921
|
-
|
1038
|
+
json_gen_cstr(gen, "data");
|
1039
|
+
json_gen_cstr(gen, RREGEXP(obj)->str);
|
922
1040
|
break;
|
923
1041
|
|
924
1042
|
case T_SCOPE:
|
925
|
-
|
1043
|
+
json_gen_cstr(gen, "scope");
|
926
1044
|
|
927
1045
|
struct SCOPE *scope = (struct SCOPE *)obj;
|
928
1046
|
if (scope->local_tbl) {
|
@@ -932,13 +1050,13 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
932
1050
|
VALUE cur = *list++;
|
933
1051
|
|
934
1052
|
if (RTEST(cur)) {
|
935
|
-
|
936
|
-
|
1053
|
+
json_gen_cstr(gen, "node");
|
1054
|
+
json_gen_value(gen, cur);
|
937
1055
|
}
|
938
1056
|
|
939
1057
|
if (n) {
|
940
|
-
|
941
|
-
|
1058
|
+
json_gen_cstr(gen, "variables");
|
1059
|
+
json_gen_map_open(gen);
|
942
1060
|
while (n--) {
|
943
1061
|
cur = *list++;
|
944
1062
|
i++;
|
@@ -946,34 +1064,34 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
946
1064
|
if (!rb_is_local_id(scope->local_tbl[i]))
|
947
1065
|
continue;
|
948
1066
|
|
949
|
-
|
950
|
-
|
1067
|
+
json_gen_id(gen, scope->local_tbl[i]);
|
1068
|
+
json_gen_value(gen, cur);
|
951
1069
|
}
|
952
|
-
|
1070
|
+
json_gen_map_close(gen);
|
953
1071
|
}
|
954
1072
|
}
|
955
1073
|
break;
|
956
1074
|
|
957
1075
|
case T_NODE:
|
958
|
-
|
1076
|
+
json_gen_cstr(gen, "node");
|
959
1077
|
|
960
|
-
|
961
|
-
|
1078
|
+
json_gen_cstr(gen, "node_type");
|
1079
|
+
json_gen_cstr(gen, nd_type_str(obj));
|
962
1080
|
|
963
|
-
|
964
|
-
|
1081
|
+
json_gen_cstr(gen, "file");
|
1082
|
+
json_gen_cstr(gen, RNODE(obj)->nd_file);
|
965
1083
|
|
966
|
-
|
967
|
-
|
1084
|
+
json_gen_cstr(gen, "line");
|
1085
|
+
json_gen_integer(gen, nd_line(obj));
|
968
1086
|
|
969
|
-
|
970
|
-
|
1087
|
+
json_gen_cstr(gen, "node_code");
|
1088
|
+
json_gen_integer(gen, nd_type(obj));
|
971
1089
|
|
972
|
-
#define PRINT_ID(sub)
|
973
|
-
#define PRINT_VAL(sub)
|
1090
|
+
#define PRINT_ID(sub) json_gen_id(gen, RNODE(obj)->sub.id)
|
1091
|
+
#define PRINT_VAL(sub) json_gen_value(gen, RNODE(obj)->sub.value)
|
974
1092
|
|
975
1093
|
int nd_type = nd_type(obj);
|
976
|
-
|
1094
|
+
json_gen_cstr(gen, "n1");
|
977
1095
|
switch(nd_type) {
|
978
1096
|
case NODE_LVAR:
|
979
1097
|
case NODE_DVAR:
|
@@ -1004,23 +1122,23 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
1004
1122
|
|
1005
1123
|
case NODE_SCOPE: {
|
1006
1124
|
ID *tbl = RNODE(obj)->nd_tbl;
|
1007
|
-
|
1125
|
+
json_gen_array_open(gen);
|
1008
1126
|
if (tbl) {
|
1009
1127
|
int size = tbl[0];
|
1010
1128
|
int i = 3;
|
1011
1129
|
|
1012
1130
|
for (; i < size+1; i++) {
|
1013
|
-
|
1131
|
+
json_gen_id(gen, tbl[i]);
|
1014
1132
|
}
|
1015
1133
|
}
|
1016
|
-
|
1134
|
+
json_gen_array_close(gen);
|
1017
1135
|
break;
|
1018
1136
|
}
|
1019
1137
|
|
1020
1138
|
case NODE_IFUNC:
|
1021
1139
|
case NODE_CFUNC: {
|
1022
1140
|
const char *name = bin_find_symbol_name((void*)RNODE(obj)->u1.value);
|
1023
|
-
|
1141
|
+
json_gen_format(gen, "0x%x: %s", RNODE(obj)->u1.value, name ? name : "???");
|
1024
1142
|
break;
|
1025
1143
|
}
|
1026
1144
|
|
@@ -1028,7 +1146,7 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
1028
1146
|
PRINT_VAL(u1);
|
1029
1147
|
}
|
1030
1148
|
|
1031
|
-
|
1149
|
+
json_gen_cstr(gen, "n2");
|
1032
1150
|
switch(nd_type) {
|
1033
1151
|
case NODE_CALL:
|
1034
1152
|
case NODE_FBODY:
|
@@ -1046,9 +1164,9 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
1046
1164
|
|
1047
1165
|
case NODE_OP_ASGN1:
|
1048
1166
|
if (RNODE(obj)->nd_mid == 0)
|
1049
|
-
|
1167
|
+
json_gen_cstr(gen, ":||");
|
1050
1168
|
else if (RNODE(obj)->nd_mid == 1)
|
1051
|
-
|
1169
|
+
json_gen_cstr(gen, ":&&");
|
1052
1170
|
else
|
1053
1171
|
PRINT_ID(u2);
|
1054
1172
|
break;
|
@@ -1058,9 +1176,9 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
1058
1176
|
PRINT_VAL(u2);
|
1059
1177
|
} else {
|
1060
1178
|
if (RNODE(obj)->nd_mid == 0)
|
1061
|
-
|
1179
|
+
json_gen_cstr(gen, ":||");
|
1062
1180
|
else if (RNODE(obj)->nd_mid == 1)
|
1063
|
-
|
1181
|
+
json_gen_cstr(gen, ":&&");
|
1064
1182
|
else
|
1065
1183
|
PRINT_ID(u2);
|
1066
1184
|
}
|
@@ -1072,13 +1190,13 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
1072
1190
|
case NODE_IFUNC:
|
1073
1191
|
case NODE_CFUNC:
|
1074
1192
|
case NODE_NEWLINE:
|
1075
|
-
|
1193
|
+
json_gen_integer(gen, RNODE(obj)->u2.argc);
|
1076
1194
|
break;
|
1077
1195
|
|
1078
1196
|
case NODE_BLOCK:
|
1079
1197
|
case NODE_ARRAY:
|
1080
1198
|
if (RNODE(obj)->u2.node == RNODE(obj))
|
1081
|
-
|
1199
|
+
json_gen_null(gen);
|
1082
1200
|
else
|
1083
1201
|
PRINT_VAL(u2);
|
1084
1202
|
break;
|
@@ -1087,10 +1205,10 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
1087
1205
|
PRINT_VAL(u2);
|
1088
1206
|
}
|
1089
1207
|
|
1090
|
-
|
1208
|
+
json_gen_cstr(gen, "n3");
|
1091
1209
|
switch(nd_type) {
|
1092
1210
|
case NODE_ARGS:
|
1093
|
-
|
1211
|
+
json_gen_integer(gen, RNODE(obj)->u3.cnt);
|
1094
1212
|
break;
|
1095
1213
|
|
1096
1214
|
case NODE_OP_ASGN2:
|
@@ -1106,171 +1224,164 @@ obj_dump(VALUE obj, yajl_gen gen)
|
|
1106
1224
|
break;
|
1107
1225
|
|
1108
1226
|
case T_STRING:
|
1109
|
-
|
1227
|
+
json_gen_cstr(gen, "string");
|
1110
1228
|
obj_dump_class(gen, obj);
|
1111
1229
|
|
1112
|
-
|
1113
|
-
|
1230
|
+
json_gen_cstr(gen, "length");
|
1231
|
+
json_gen_integer(gen, RSTRING_LEN(obj));
|
1114
1232
|
|
1115
1233
|
if (FL_TEST(obj, ELTS_SHARED|FL_USER3)) {
|
1116
|
-
|
1117
|
-
|
1234
|
+
json_gen_cstr(gen, "shared");
|
1235
|
+
json_gen_value(gen, RSTRING(obj)->aux.shared);
|
1118
1236
|
|
1119
|
-
|
1120
|
-
|
1237
|
+
json_gen_cstr(gen, "flags");
|
1238
|
+
json_gen_array_open(gen);
|
1121
1239
|
if (FL_TEST(obj, ELTS_SHARED))
|
1122
|
-
|
1240
|
+
json_gen_cstr(gen, "elts_shared");
|
1123
1241
|
if (FL_TEST(obj, FL_USER3))
|
1124
|
-
|
1125
|
-
|
1242
|
+
json_gen_cstr(gen, "str_assoc");
|
1243
|
+
json_gen_array_close(gen);
|
1126
1244
|
} else {
|
1127
|
-
|
1128
|
-
|
1245
|
+
json_gen_cstr(gen, "data");
|
1246
|
+
json_gen_string(gen, (unsigned char *)RSTRING_PTR(obj), RSTRING_LEN(obj));
|
1129
1247
|
}
|
1130
1248
|
break;
|
1131
1249
|
|
1132
1250
|
case T_VARMAP:
|
1133
|
-
|
1251
|
+
json_gen_cstr(gen, "varmap");
|
1134
1252
|
obj_dump_class(gen, obj);
|
1135
1253
|
|
1136
1254
|
struct RVarmap *vars = (struct RVarmap *)obj;
|
1137
1255
|
|
1138
1256
|
if (vars->next) {
|
1139
|
-
|
1140
|
-
|
1257
|
+
json_gen_cstr(gen, "next");
|
1258
|
+
json_gen_value(gen, (VALUE)vars->next);
|
1141
1259
|
}
|
1142
1260
|
|
1143
1261
|
if (vars->id) {
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1262
|
+
json_gen_cstr(gen, "data");
|
1263
|
+
json_gen_map_open(gen);
|
1264
|
+
json_gen_id(gen, vars->id);
|
1265
|
+
json_gen_value(gen, vars->val);
|
1266
|
+
json_gen_map_close(gen);
|
1149
1267
|
}
|
1150
1268
|
break;
|
1151
1269
|
|
1152
1270
|
case T_CLASS:
|
1153
1271
|
case T_MODULE:
|
1154
1272
|
case T_ICLASS:
|
1155
|
-
|
1273
|
+
json_gen_cstr(gen, type==T_CLASS ? "class" : type==T_MODULE ? "module" : "iclass");
|
1156
1274
|
obj_dump_class(gen, obj);
|
1157
1275
|
|
1158
|
-
|
1276
|
+
json_gen_cstr(gen, "name");
|
1159
1277
|
VALUE name = rb_classname(obj);
|
1160
1278
|
if (RTEST(name))
|
1161
|
-
|
1279
|
+
json_gen_cstr(gen, RSTRING_PTR(name));
|
1162
1280
|
else
|
1163
|
-
|
1281
|
+
json_gen_cstr(gen, 0);
|
1164
1282
|
|
1165
|
-
|
1166
|
-
|
1283
|
+
json_gen_cstr(gen, "super");
|
1284
|
+
json_gen_value(gen, RCLASS(obj)->super);
|
1167
1285
|
|
1168
1286
|
if (RTEST(RCLASS(obj)->super)) {
|
1169
|
-
|
1287
|
+
json_gen_cstr(gen, "super_name");
|
1170
1288
|
VALUE super_name = rb_classname(RCLASS(obj)->super);
|
1171
1289
|
if (RTEST(super_name))
|
1172
|
-
|
1290
|
+
json_gen_cstr(gen, RSTRING_PTR(super_name));
|
1173
1291
|
else
|
1174
|
-
|
1292
|
+
json_gen_cstr(gen, 0);
|
1175
1293
|
}
|
1176
1294
|
|
1177
1295
|
if (FL_TEST(obj, FL_SINGLETON)) {
|
1178
|
-
|
1179
|
-
|
1296
|
+
json_gen_cstr(gen, "singleton");
|
1297
|
+
json_gen_bool(gen, 1);
|
1180
1298
|
}
|
1181
1299
|
|
1182
1300
|
if (RCLASS(obj)->iv_tbl && RCLASS(obj)->iv_tbl->num_entries) {
|
1183
|
-
|
1184
|
-
|
1301
|
+
json_gen_cstr(gen, "ivars");
|
1302
|
+
json_gen_map_open(gen);
|
1185
1303
|
st_foreach(RCLASS(obj)->iv_tbl, each_ivar, (st_data_t)gen);
|
1186
|
-
|
1304
|
+
json_gen_map_close(gen);
|
1187
1305
|
}
|
1188
1306
|
|
1189
1307
|
if (RCLASS(obj)->m_tbl && RCLASS(obj)->m_tbl->num_entries) {
|
1190
|
-
|
1191
|
-
|
1308
|
+
json_gen_cstr(gen, "methods");
|
1309
|
+
json_gen_map_open(gen);
|
1192
1310
|
st_foreach(RCLASS(obj)->m_tbl, each_ivar, (st_data_t)gen);
|
1193
|
-
|
1311
|
+
json_gen_map_close(gen);
|
1194
1312
|
}
|
1195
1313
|
break;
|
1196
1314
|
|
1197
1315
|
case T_OBJECT:
|
1198
|
-
|
1316
|
+
json_gen_cstr(gen, "object");
|
1199
1317
|
obj_dump_class(gen, obj);
|
1200
1318
|
|
1201
1319
|
struct RClass *klass = RCLASS(obj);
|
1202
1320
|
|
1203
1321
|
if (klass->iv_tbl && klass->iv_tbl->num_entries) {
|
1204
|
-
|
1205
|
-
|
1322
|
+
json_gen_cstr(gen, "ivars");
|
1323
|
+
json_gen_map_open(gen);
|
1206
1324
|
st_foreach(klass->iv_tbl, each_ivar, (st_data_t)gen);
|
1207
|
-
|
1325
|
+
json_gen_map_close(gen);
|
1208
1326
|
}
|
1209
1327
|
break;
|
1210
1328
|
|
1211
1329
|
case T_ARRAY:
|
1212
|
-
|
1330
|
+
json_gen_cstr(gen, "array");
|
1213
1331
|
obj_dump_class(gen, obj);
|
1214
1332
|
|
1215
1333
|
struct RArray *ary = RARRAY(obj);
|
1216
1334
|
|
1217
|
-
|
1218
|
-
|
1335
|
+
json_gen_cstr(gen, "length");
|
1336
|
+
json_gen_integer(gen, ary->len);
|
1219
1337
|
|
1220
1338
|
if (FL_TEST(obj, ELTS_SHARED)) {
|
1221
|
-
|
1222
|
-
|
1339
|
+
json_gen_cstr(gen, "shared");
|
1340
|
+
json_gen_value(gen, ary->aux.shared);
|
1223
1341
|
} else if (ary->len) {
|
1224
|
-
|
1225
|
-
|
1342
|
+
json_gen_cstr(gen, "data");
|
1343
|
+
json_gen_array_open(gen);
|
1226
1344
|
int i;
|
1227
1345
|
for(i=0; i < ary->len; i++)
|
1228
|
-
|
1229
|
-
|
1346
|
+
json_gen_value(gen, ary->ptr[i]);
|
1347
|
+
json_gen_array_close(gen);
|
1230
1348
|
}
|
1231
1349
|
break;
|
1232
1350
|
|
1233
1351
|
case T_HASH:
|
1234
|
-
|
1352
|
+
json_gen_cstr(gen, "hash");
|
1235
1353
|
obj_dump_class(gen, obj);
|
1236
1354
|
|
1237
1355
|
struct RHash *hash = RHASH(obj);
|
1238
1356
|
|
1239
|
-
|
1357
|
+
json_gen_cstr(gen, "length");
|
1240
1358
|
if (hash->tbl)
|
1241
|
-
|
1359
|
+
json_gen_integer(gen, hash->tbl->num_entries);
|
1242
1360
|
else
|
1243
|
-
|
1361
|
+
json_gen_integer(gen, 0);
|
1244
1362
|
|
1245
|
-
|
1246
|
-
|
1363
|
+
json_gen_cstr(gen, "default");
|
1364
|
+
json_gen_value(gen, hash->ifnone);
|
1247
1365
|
|
1248
1366
|
if (hash->tbl && hash->tbl->num_entries) {
|
1249
|
-
|
1250
|
-
//
|
1251
|
-
|
1367
|
+
json_gen_cstr(gen, "data");
|
1368
|
+
//json_gen_map_open(gen);
|
1369
|
+
json_gen_array_open(gen);
|
1252
1370
|
st_foreach(hash->tbl, each_hash_entry, (st_data_t)gen);
|
1253
|
-
|
1254
|
-
//
|
1371
|
+
json_gen_array_close(gen);
|
1372
|
+
//json_gen_map_close(gen);
|
1255
1373
|
}
|
1256
1374
|
break;
|
1257
1375
|
|
1258
1376
|
default:
|
1259
|
-
|
1377
|
+
json_gen_cstr(gen, "unknown");
|
1260
1378
|
obj_dump_class(gen, obj);
|
1261
1379
|
}
|
1262
1380
|
|
1263
|
-
|
1264
|
-
|
1381
|
+
json_gen_cstr(gen, "code");
|
1382
|
+
json_gen_integer(gen, BUILTIN_TYPE(obj));
|
1265
1383
|
|
1266
|
-
|
1267
|
-
}
|
1268
|
-
|
1269
|
-
static int
|
1270
|
-
objs_each_dump(st_data_t key, st_data_t record, st_data_t arg)
|
1271
|
-
{
|
1272
|
-
obj_dump((VALUE)key, (yajl_gen)arg);
|
1273
|
-
return ST_CONTINUE;
|
1384
|
+
json_gen_map_close(gen);
|
1274
1385
|
}
|
1275
1386
|
|
1276
1387
|
extern st_table *rb_global_tbl;
|
@@ -1278,89 +1389,89 @@ extern st_table *rb_global_tbl;
|
|
1278
1389
|
static int
|
1279
1390
|
globals_each_dump(st_data_t key, st_data_t record, st_data_t arg)
|
1280
1391
|
{
|
1281
|
-
|
1282
|
-
|
1392
|
+
json_gen_id((json_gen)arg, (ID)key);
|
1393
|
+
json_gen_value((json_gen)arg, rb_gvar_get((void*)record));
|
1283
1394
|
return ST_CONTINUE;
|
1284
1395
|
}
|
1285
1396
|
|
1286
1397
|
static int
|
1287
1398
|
finalizers_each_dump(st_data_t key, st_data_t val, st_data_t arg)
|
1288
1399
|
{
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1400
|
+
json_gen gen = (json_gen)arg;
|
1401
|
+
json_gen_array_open(gen);
|
1402
|
+
json_gen_value(gen, (VALUE)key);
|
1403
|
+
json_gen_value(gen, (VALUE)val);
|
1404
|
+
json_gen_array_close(gen);
|
1294
1405
|
return ST_CONTINUE;
|
1295
1406
|
}
|
1296
1407
|
|
1297
1408
|
static void
|
1298
|
-
memprof_dump_globals(
|
1409
|
+
memprof_dump_globals(json_gen gen)
|
1299
1410
|
{
|
1300
|
-
|
1411
|
+
json_gen_map_open(gen);
|
1301
1412
|
|
1302
|
-
|
1303
|
-
|
1413
|
+
json_gen_cstr(gen, "_id");
|
1414
|
+
json_gen_cstr(gen, "globals");
|
1304
1415
|
|
1305
|
-
|
1306
|
-
|
1416
|
+
json_gen_cstr(gen, "type");
|
1417
|
+
json_gen_cstr(gen, "globals");
|
1307
1418
|
|
1308
|
-
|
1419
|
+
json_gen_cstr(gen, "variables");
|
1309
1420
|
|
1310
|
-
|
1421
|
+
json_gen_map_open(gen);
|
1311
1422
|
st_foreach(rb_global_tbl, globals_each_dump, (st_data_t)gen);
|
1312
|
-
|
1423
|
+
json_gen_map_close(gen);
|
1313
1424
|
|
1314
|
-
|
1315
|
-
|
1425
|
+
json_gen_map_close(gen);
|
1426
|
+
json_gen_reset(gen);
|
1316
1427
|
}
|
1317
1428
|
|
1318
1429
|
static void
|
1319
|
-
memprof_dump_stack_frame(
|
1430
|
+
memprof_dump_stack_frame(json_gen gen, struct FRAME *frame)
|
1320
1431
|
{
|
1321
|
-
|
1432
|
+
json_gen_map_open(gen);
|
1322
1433
|
|
1323
|
-
|
1324
|
-
|
1434
|
+
json_gen_cstr(gen, "_id");
|
1435
|
+
json_gen_pointer(gen, frame);
|
1325
1436
|
|
1326
|
-
|
1327
|
-
|
1437
|
+
json_gen_cstr(gen, "type");
|
1438
|
+
json_gen_cstr(gen, "frame");
|
1328
1439
|
|
1329
|
-
|
1330
|
-
|
1440
|
+
json_gen_cstr(gen, "self");
|
1441
|
+
json_gen_value(gen, frame->self);
|
1331
1442
|
|
1332
1443
|
if (frame->last_class) {
|
1333
|
-
|
1334
|
-
|
1444
|
+
json_gen_cstr(gen, "last_class");
|
1445
|
+
json_gen_value(gen, frame->last_class);
|
1335
1446
|
}
|
1336
1447
|
|
1337
1448
|
if (frame->orig_func) {
|
1338
|
-
|
1339
|
-
|
1449
|
+
json_gen_cstr(gen, "orig_func");
|
1450
|
+
json_gen_id(gen, frame->orig_func);
|
1340
1451
|
}
|
1341
1452
|
|
1342
1453
|
if (frame->last_func && frame->last_func != frame->orig_func) {
|
1343
|
-
|
1344
|
-
|
1454
|
+
json_gen_cstr(gen, "last_func");
|
1455
|
+
json_gen_id(gen, frame->last_func);
|
1345
1456
|
}
|
1346
1457
|
|
1347
1458
|
if (frame->node) {
|
1348
|
-
|
1349
|
-
|
1459
|
+
json_gen_cstr(gen, "node");
|
1460
|
+
json_gen_pointer(gen, (void*)frame->node);
|
1350
1461
|
}
|
1351
1462
|
|
1352
1463
|
if (frame->prev) {
|
1353
|
-
|
1354
|
-
|
1464
|
+
json_gen_cstr(gen, "prev");
|
1465
|
+
json_gen_pointer(gen, (void*)frame->prev);
|
1355
1466
|
}
|
1356
1467
|
|
1357
1468
|
if (frame->tmp) {
|
1358
|
-
|
1359
|
-
|
1469
|
+
json_gen_cstr(gen, "tmp");
|
1470
|
+
json_gen_pointer(gen, (void*)frame->tmp);
|
1360
1471
|
}
|
1361
1472
|
|
1362
|
-
|
1363
|
-
|
1473
|
+
json_gen_map_close(gen);
|
1474
|
+
json_gen_reset(gen);
|
1364
1475
|
|
1365
1476
|
if (frame->prev) {
|
1366
1477
|
memprof_dump_stack_frame(gen, frame->prev);
|
@@ -1368,13 +1479,13 @@ memprof_dump_stack_frame(yajl_gen gen, struct FRAME *frame)
|
|
1368
1479
|
}
|
1369
1480
|
|
1370
1481
|
static void
|
1371
|
-
memprof_dump_stack(
|
1482
|
+
memprof_dump_stack(json_gen gen)
|
1372
1483
|
{
|
1373
1484
|
memprof_dump_stack_frame(gen, ruby_frame);
|
1374
1485
|
}
|
1375
1486
|
|
1376
1487
|
static void
|
1377
|
-
memprof_dump_lsof(
|
1488
|
+
memprof_dump_lsof(json_gen gen)
|
1378
1489
|
{
|
1379
1490
|
VALUE cmd = rb_str_new2("lsof -np ");
|
1380
1491
|
VALUE pid = rb_funcall(rb_mProcess, rb_intern("pid"), 0);
|
@@ -1388,31 +1499,31 @@ memprof_dump_lsof(yajl_gen gen)
|
|
1388
1499
|
for (i=1; i < RARRAY_LEN(lines); i++) {
|
1389
1500
|
VALUE parts = rb_funcall(RARRAY_PTR(lines)[i], rb_intern("split"), 2, Qnil, INT2FIX(9));
|
1390
1501
|
|
1391
|
-
|
1502
|
+
json_gen_map_open(gen);
|
1392
1503
|
|
1393
|
-
|
1394
|
-
|
1504
|
+
json_gen_cstr(gen, "_id");
|
1505
|
+
json_gen_format(gen, "lsof:%d", i);
|
1395
1506
|
|
1396
|
-
|
1397
|
-
|
1507
|
+
json_gen_cstr(gen, "type");
|
1508
|
+
json_gen_cstr(gen, "lsof");
|
1398
1509
|
|
1399
|
-
|
1400
|
-
|
1510
|
+
json_gen_cstr(gen, "fd");
|
1511
|
+
json_gen_cstr(gen, RSTRING_PTR(RARRAY_PTR(parts)[3]));
|
1401
1512
|
|
1402
|
-
|
1403
|
-
|
1513
|
+
json_gen_cstr(gen, "fd_type");
|
1514
|
+
json_gen_cstr(gen, RSTRING_PTR(RARRAY_PTR(parts)[4]));
|
1404
1515
|
|
1405
|
-
|
1406
|
-
|
1516
|
+
json_gen_cstr(gen, "fd_name");
|
1517
|
+
json_gen_cstr(gen, RSTRING_PTR(RARRAY_PTR(parts)[RARRAY_LEN(parts)-1]));
|
1407
1518
|
|
1408
|
-
|
1409
|
-
|
1519
|
+
json_gen_map_close(gen);
|
1520
|
+
json_gen_reset(gen);
|
1410
1521
|
}
|
1411
1522
|
}
|
1412
1523
|
}
|
1413
1524
|
|
1414
1525
|
static void
|
1415
|
-
memprof_dump_ps(
|
1526
|
+
memprof_dump_ps(json_gen gen)
|
1416
1527
|
{
|
1417
1528
|
VALUE cmd = rb_str_new2("ps -o rss,vsize -p ");
|
1418
1529
|
VALUE pid = rb_funcall(rb_mProcess, rb_intern("pid"), 0);
|
@@ -1426,93 +1537,80 @@ memprof_dump_ps(yajl_gen gen)
|
|
1426
1537
|
if (RARRAY_LEN(lines) == 2) {
|
1427
1538
|
VALUE parts = rb_funcall(RARRAY_PTR(lines)[1], rb_intern("split"), 0);
|
1428
1539
|
|
1429
|
-
|
1540
|
+
json_gen_map_open(gen);
|
1430
1541
|
|
1431
|
-
|
1432
|
-
|
1542
|
+
json_gen_cstr(gen, "_id");
|
1543
|
+
json_gen_cstr(gen, "ps");
|
1433
1544
|
|
1434
|
-
|
1435
|
-
|
1545
|
+
json_gen_cstr(gen, "type");
|
1546
|
+
json_gen_cstr(gen, "ps");
|
1436
1547
|
|
1437
|
-
|
1438
|
-
|
1548
|
+
json_gen_cstr(gen, "rss");
|
1549
|
+
json_gen_cstr(gen, RSTRING_PTR(RARRAY_PTR(parts)[0]));
|
1439
1550
|
|
1440
|
-
|
1441
|
-
|
1551
|
+
json_gen_cstr(gen, "vsize");
|
1552
|
+
json_gen_cstr(gen, RSTRING_PTR(RARRAY_PTR(parts)[1]));
|
1442
1553
|
|
1443
|
-
|
1444
|
-
|
1554
|
+
json_gen_map_close(gen);
|
1555
|
+
json_gen_reset(gen);
|
1445
1556
|
}
|
1446
1557
|
}
|
1447
1558
|
}
|
1448
1559
|
|
1449
1560
|
static void
|
1450
|
-
memprof_dump_finalizers(
|
1561
|
+
memprof_dump_finalizers(json_gen gen)
|
1451
1562
|
{
|
1452
1563
|
st_table *finalizer_table = *(st_table **)memprof_config.finalizer_table;
|
1453
1564
|
if (finalizer_table) {
|
1454
|
-
|
1565
|
+
json_gen_map_open(gen);
|
1455
1566
|
|
1456
|
-
|
1457
|
-
|
1567
|
+
json_gen_cstr(gen, "_id");
|
1568
|
+
json_gen_cstr(gen, "finalizers");
|
1458
1569
|
|
1459
|
-
|
1460
|
-
|
1570
|
+
json_gen_cstr(gen, "type");
|
1571
|
+
json_gen_cstr(gen, "finalizers");
|
1461
1572
|
|
1462
|
-
|
1463
|
-
|
1573
|
+
json_gen_cstr(gen, "data");
|
1574
|
+
json_gen_array_open(gen);
|
1464
1575
|
st_foreach(finalizer_table, finalizers_each_dump, (st_data_t)gen);
|
1465
|
-
|
1576
|
+
json_gen_array_close(gen);
|
1466
1577
|
|
1467
|
-
|
1468
|
-
|
1578
|
+
json_gen_map_close(gen);
|
1579
|
+
json_gen_reset(gen);
|
1469
1580
|
}
|
1470
1581
|
}
|
1471
1582
|
|
1472
|
-
static
|
1473
|
-
|
1583
|
+
static int
|
1584
|
+
objs_each_dump(st_data_t key, st_data_t record, st_data_t arg)
|
1474
1585
|
{
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
written += fwrite(str + written, sizeof(char), len - written, out ? out : stdout);
|
1479
|
-
if (written == len) break;
|
1480
|
-
}
|
1586
|
+
obj_dump((VALUE)key, (json_gen)arg);
|
1587
|
+
json_gen_reset((json_gen)arg);
|
1588
|
+
return ST_CONTINUE;
|
1481
1589
|
}
|
1482
1590
|
|
1483
1591
|
static VALUE
|
1484
1592
|
memprof_dump(int argc, VALUE *argv, VALUE self)
|
1485
1593
|
{
|
1486
|
-
VALUE
|
1487
|
-
|
1594
|
+
VALUE ret = Qnil;
|
1595
|
+
int old = track_objs;
|
1488
1596
|
|
1489
|
-
if (
|
1597
|
+
if (rb_block_given_p()) {
|
1598
|
+
memprof_start(self);
|
1599
|
+
ret = rb_yield(Qnil);
|
1600
|
+
} else if (!track_objs)
|
1490
1601
|
rb_raise(rb_eRuntimeError, "object tracking disabled, call Memprof.start first");
|
1491
1602
|
|
1492
|
-
rb_scan_args(argc, argv, "01", &str);
|
1493
|
-
|
1494
|
-
if (RTEST(str)) {
|
1495
|
-
out = fopen(StringValueCStr(str), "w");
|
1496
|
-
if (!out)
|
1497
|
-
rb_raise(rb_eArgError, "unable to open output file");
|
1498
|
-
}
|
1499
|
-
|
1500
|
-
yajl_gen_config conf = { .beautify = 1, .indentString = " " };
|
1501
|
-
yajl_gen gen = yajl_gen_alloc2((yajl_print_t)&json_print, &conf, NULL, (void*)out);
|
1502
|
-
|
1503
1603
|
track_objs = 0;
|
1504
1604
|
|
1505
|
-
|
1605
|
+
json_gen gen = json_for_args(argc, argv);
|
1506
1606
|
st_foreach(objs, objs_each_dump, (st_data_t)gen);
|
1507
|
-
|
1508
|
-
yajl_gen_free(gen);
|
1509
|
-
|
1510
|
-
if (out)
|
1511
|
-
fclose(out);
|
1607
|
+
json_free(gen);
|
1512
1608
|
|
1513
|
-
|
1609
|
+
if (rb_block_given_p())
|
1610
|
+
memprof_stop(self);
|
1611
|
+
track_objs = old;
|
1514
1612
|
|
1515
|
-
return
|
1613
|
+
return ret;
|
1516
1614
|
}
|
1517
1615
|
|
1518
1616
|
static VALUE
|
@@ -1550,8 +1648,8 @@ memprof_dump_all(int argc, VALUE *argv, VALUE self)
|
|
1550
1648
|
rb_raise(rb_eArgError, "unable to open output file");
|
1551
1649
|
}
|
1552
1650
|
|
1553
|
-
|
1554
|
-
|
1651
|
+
json_gen_config conf = { .beautify = 0, .indentString = " " };
|
1652
|
+
json_gen gen = json_gen_alloc2((json_print_t)&json_print, &conf, NULL, (void*)out);
|
1555
1653
|
|
1556
1654
|
track_objs = 0;
|
1557
1655
|
|
@@ -1567,7 +1665,7 @@ memprof_dump_all(int argc, VALUE *argv, VALUE self)
|
|
1567
1665
|
while (p < pend) {
|
1568
1666
|
if (RBASIC(p)->flags) {
|
1569
1667
|
obj_dump((VALUE)p, gen);
|
1570
|
-
|
1668
|
+
json_gen_reset(gen);
|
1571
1669
|
}
|
1572
1670
|
|
1573
1671
|
p += memprof_config.sizeof_RVALUE;
|
@@ -1577,8 +1675,8 @@ memprof_dump_all(int argc, VALUE *argv, VALUE self)
|
|
1577
1675
|
memprof_dump_lsof(gen);
|
1578
1676
|
memprof_dump_ps(gen);
|
1579
1677
|
|
1580
|
-
|
1581
|
-
|
1678
|
+
json_gen_clear(gen);
|
1679
|
+
json_gen_free(gen);
|
1582
1680
|
|
1583
1681
|
if (out) {
|
1584
1682
|
fclose(out);
|
@@ -1824,7 +1922,10 @@ Init_memprof()
|
|
1824
1922
|
rb_define_singleton_method(memprof, "track", memprof_track, -1);
|
1825
1923
|
rb_define_singleton_method(memprof, "dump", memprof_dump, -1);
|
1826
1924
|
rb_define_singleton_method(memprof, "dump_all", memprof_dump_all, -1);
|
1827
|
-
rb_define_singleton_method(memprof, "
|
1925
|
+
rb_define_singleton_method(memprof, "trace", memprof_trace, -1);
|
1926
|
+
rb_define_singleton_method(memprof, "trace_request", memprof_trace_request, 1);
|
1927
|
+
rb_define_singleton_method(memprof, "trace_filename", memprof_trace_filename_get, 0);
|
1928
|
+
rb_define_singleton_method(memprof, "trace_filename=", memprof_trace_filename_set, -1);
|
1828
1929
|
|
1829
1930
|
objs = st_init_numtable();
|
1830
1931
|
init_memprof_config_base();
|
@@ -1833,6 +1934,11 @@ Init_memprof()
|
|
1833
1934
|
create_tramp_table();
|
1834
1935
|
|
1835
1936
|
install_malloc_tracer();
|
1937
|
+
install_gc_tracer();
|
1938
|
+
install_objects_tracer();
|
1939
|
+
install_fd_tracer();
|
1940
|
+
install_mysql_tracer();
|
1941
|
+
install_memcache_tracer();
|
1836
1942
|
|
1837
1943
|
gc_hook = Data_Wrap_Struct(rb_cObject, sourcefile_marker, NULL, NULL);
|
1838
1944
|
rb_global_variable(&gc_hook);
|