Guest User

Untitled

a guest
Feb 20th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.20 KB | None | 0 0
  1. #include <time.h>
  2. #include "snapshot.h"
  3.  
  4. static VALUE rb_mB;
  5. static VALUE rb_cC;
  6.  
  7. /* Number of filled <tt>heaps_slots</tt> */
  8. static VALUE heaps_used(VALUE self) {
  9. return INT2FIX(rb_gc_heaps_used());
  10. }
  11.  
  12. /* Number of allocated <tt>heaps_slots</tt> */
  13. static VALUE heaps_length(VALUE self) {
  14. return INT2FIX(rb_gc_heaps_length());
  15. }
  16.  
  17. /* Walk the live, instrumented objects on the heap and write them to <tt>_logfile</tt>. */
  18. static VALUE snapshot(VALUE self, VALUE _logfile) {
  19. Check_Type(_logfile, T_STRING);
  20.  
  21. RVALUE *obj, *obj_end;
  22. st_table_entry *sym;
  23.  
  24. struct heaps_slot * heaps = rb_gc_heap_slots();
  25. struct st_table * sym_tbl = rb_parse_sym_tbl();
  26.  
  27. /* see if the logfile exists already */
  28. FILE *logfile = fopen(StringValueCStr(_logfile), "r");
  29. int is_new;
  30. if (!(is_new = (logfile == NULL)))
  31. fclose(logfile);
  32.  
  33. /* reopen for writing */
  34. if ((logfile = fopen(StringValueCStr(_logfile), "w")) == NULL)
  35. rb_raise(rb_eRuntimeError, "couldn't open snapshot file");
  36.  
  37. int filled_slots = 0;
  38. int free_slots = 0;
  39.  
  40. int i;
  41. char * chr;
  42.  
  43. for (i = 0; i < 3; i++) {
  44. /* request GC run */
  45. rb_funcall(rb_mGC, rb_intern("start"), 0);
  46. rb_thread_schedule();
  47. }
  48.  
  49. /* walk the heap */
  50. for (i = 0; i < rb_gc_heaps_used(); i++) {
  51. obj = heaps[i].slot;
  52. obj_end = obj + heaps[i].limit;
  53. for (; obj < obj_end; obj++) {
  54. if (obj->as.basic.flags) { /* always 0 for freed objects */
  55. filled_slots ++;
  56.  
  57. /* write the source file*/
  58. if (obj->file) {
  59. chr = obj->file;
  60. if (*chr != '\0') {
  61. fprintf(logfile, "%s", obj->file);
  62. } else {
  63. fprintf(logfile, "__empty__");
  64. }
  65. } else {
  66. fprintf(logfile, "__null__");
  67. }
  68.  
  69. /* write the source line */
  70. fprintf(logfile, ":");
  71. if (obj->line) {
  72. fprintf(logfile, "%i", obj->line);
  73. } else {
  74. fprintf(logfile, "__null__");
  75. }
  76.  
  77. /* write the class */
  78. fprintf(logfile, ":");
  79. switch (TYPE(obj)) {
  80. case T_NONE:
  81. fprintf(logfile, "__none__"); break;
  82. case T_BLKTAG:
  83. fprintf(logfile, "__blktag__"); break;
  84. case T_UNDEF:
  85. fprintf(logfile, "__undef__"); break;
  86. case T_VARMAP:
  87. fprintf(logfile, "__varmap__"); break;
  88. case T_SCOPE:
  89. fprintf(logfile, "__scope__"); break;
  90. case T_NODE:
  91. fprintf(logfile, "__node__"); break;
  92. default:
  93. if (!obj->as.basic.klass) {
  94. fprintf(logfile, "__unknown__");
  95. } else {
  96. fprintf(logfile, rb_obj_classname((VALUE)obj));
  97. }
  98. }
  99.  
  100. /* write newline */
  101. fprintf(logfile, "\n");
  102. } else {
  103. free_slots ++;
  104. }
  105. }
  106. }
  107.  
  108. /* walk the symbol table */
  109. /* hashed = lookup_builtin("Symbol");
  110. for (i = 0; i < sym_tbl->num_bins; i++) {
  111. for (sym = sym_tbl->bins[i]; sym != 0; sym = sym->next) {
  112. fprintf(logfile, "%i,%lu\n", hashed + 1, sym->record);
  113. }
  114. } */
  115.  
  116. fprintf(logfile, "%i filled\n", filled_slots);
  117. fprintf(logfile, "%i free\n", free_slots);
  118. fclose(logfile);
  119.  
  120. return Qnil;
  121. }
  122.  
  123.  
  124. /*
  125.  
  126. This class performs the actual object logging of BleakHouse. To use it directly, you need to make calls to BleakHouse.snapshot.
  127.  
  128. By default, BleakHouse records a snapshot on exit. You can disable this by setting the environment variable <tt>NO_EXIT_HANDLER</tt> before startup.
  129.  
  130. It is also possible to externally trigger the snapshot at any time by sending <tt>SIGUSR2</tt> to the process.
  131.  
  132. == Example
  133.  
  134. At the start of your app, put:
  135. require 'rubygems'
  136. require 'bleak_house'
  137. $logfile = "/path/to/logfile"
  138.  
  139. Run your app. Once it exits, analyze your data:
  140. bleak /path/to/logfile
  141.  
  142. */
  143. void
  144. Init_snapshot()
  145. {
  146. rb_mB = rb_define_module("BleakHouse");
  147. rb_define_singleton_method(rb_mB, "snapshot", snapshot, 1);
  148. rb_define_singleton_method(rb_mB, "heaps_used", heaps_used, 0);
  149. rb_define_singleton_method(rb_mB, "heaps_length", heaps_length, 0);
  150. }
Add Comment
Please, Sign In to add comment