memprof 0.3.2 → 0.3.3
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/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);
|