Class: BleakHouse::Logger
- Inherits:
-
Object
- Object
- BleakHouse::Logger
- Defined in:
- lib/bleak_house/logger/mem_usage.rb,
ext/bleak_house/logger/snapshot.c
Instance Method Summary collapse
-
#heaps_length ⇒ Object
Length of the struct heaps_slots allocated.
-
#heaps_used ⇒ Object
Number of struct heaps_slots used.
-
#mem_usage ⇒ Object
Returns an array of the running process’s real and virtual memory usage, in kilobytes.
-
#snapshot(_logfile, tag, _specials) ⇒ Object
Count the live objects on the heap and in the symbol table and write a CSV frame to
_logfile.
Instance Method Details
#heaps_length ⇒ Object
Length of the struct heaps_slots allocated
13 14 15 |
# File 'ext/bleak_house/logger/snapshot.c', line 13 static VALUE heaps_length(VALUE self) { return INT2FIX(rb_gc_heaps_length()); } |
#heaps_used ⇒ Object
Number of struct heaps_slots used
8 9 10 |
# File 'ext/bleak_house/logger/snapshot.c', line 8 static VALUE heaps_used(VALUE self) { return INT2FIX(rb_gc_heaps_used()); } |
#mem_usage ⇒ Object
Returns an array of the running process’s real and virtual memory usage, in kilobytes.
7 8 9 10 |
# File 'lib/bleak_house/logger/mem_usage.rb', line 7 def mem_usage a = `ps -o vsz,rss -p #{Process.pid}`.split(/\s+/)[-2..-1].map{|el| el.to_i} [a.first - a.last, a.last] end |
#snapshot(_logfile, tag, _specials) ⇒ Object
Count the live objects on the heap and in the symbol table and write a CSV frame to _logfile. Set _specials = true if you also want to count AST nodes and var scopes; otherwise, use false. Note that common classes in the CSV output are hashed to small integers in order to save space.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'ext/bleak_house/logger/snapshot.c', line 18 static VALUE snapshot(VALUE self, VALUE _logfile, VALUE tag, VALUE _specials) { Check_Type(_logfile, T_STRING); Check_Type(tag, T_STRING); RVALUE *obj, *obj_end; st_table_entry *sym, *sym_end; struct heaps_slot * heaps = rb_gc_heap_slots(); struct st_table * sym_tbl = rb_parse_sym_tbl(); int specials = RTEST(_specials); int hashed; /* see if the logfile exists already */ FILE *logfile = fopen(StringValueCStr(_logfile), "r"); int is_new; if (!(is_new = (logfile == NULL))) fclose(logfile); /* reopen for writing */ if ((logfile = fopen(StringValueCStr(_logfile), "a+")) == NULL) rb_raise(rb_eRuntimeError, "couldn't open snapshot file"); /* write the time */ fprintf(logfile, "-1,%i\n", time(0)); /* get and write the memory usage */ VALUE mem = rb_funcall(self, rb_intern("mem_usage"), 0); fprintf(logfile, "-2,%i\n", NUM2INT(RARRAY_PTR(mem)[0])); fprintf(logfile, "-3,%i\n", NUM2INT(RARRAY_PTR(mem)[1])); int current_pos = 0; int filled_slots = 0; int free_slots = 0; /* write the tag header */ fprintf(logfile, "-4,%s\n", StringValueCStr(tag)); int i, j; /* walk the heap */ for (i = 0; i < rb_gc_heaps_used(); i++) { obj = heaps[i].slot; obj_end = obj + heaps[i].limit; for (; obj < obj_end; obj++) { if (obj->as.basic.flags) { /* always 0 for freed objects */ filled_slots ++; switch (TYPE(obj)) { case T_NONE: hashed = BUILTINS_SIZE + 0; break; case T_BLKTAG: hashed = BUILTINS_SIZE + 1; break; case T_UNDEF: hashed = BUILTINS_SIZE + 2; break; case T_VARMAP: hashed = BUILTINS_SIZE + 3; break; case T_SCOPE: hashed = BUILTINS_SIZE + 4; break; case T_NODE: hashed = BUILTINS_SIZE + 5; break; default: if (!obj->as.basic.klass) { hashed = BUILTINS_SIZE + 6; } else { hashed = lookup_builtin(rb_obj_classname((VALUE)obj)); } } /* write to log */ if (hashed < 0) { /* regular classname */ fprintf(logfile, "%s,%lu\n", rb_obj_classname((VALUE)obj), FIX2ULONG(rb_obj_id((VALUE)obj))); } else { /* builtins key */ if (specials || hashed < BUILTINS_SIZE) { /* 0 is not used for 'hashed' because Ruby's to_i turns any String into 0 */ fprintf(logfile, "%i,%lu\n", hashed + 1, FIX2ULONG(rb_obj_id((VALUE)obj))); } } } else { free_slots ++; } } } /* walk the symbol table */ hashed = lookup_builtin("Symbol"); for (i = 0; i < sym_tbl->num_bins; i++) { for (sym = sym_tbl->bins[i]; sym != 0; sym = sym->next) { fprintf(logfile, "%i,%lu\n", hashed + 1, sym->record); } } fprintf(logfile, "-5,%i\n", filled_slots); fprintf(logfile, "-6,%i\n", free_slots); fclose(logfile); rb_funcall(rb_mGC, rb_intern("start"), 0); /* request GC run */ return Qtrue; } |