Guest User

Untitled

a guest
Feb 21st, 2018
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.58 KB | None | 0 0
  1. Index: intern.h
  2. ===================================================================
  3. --- intern.h (revision 20354)
  4. +++ intern.h (working copy)
  5. @@ -269,6 +269,15 @@
  6. VALUE rb_gc_enable _((void));
  7. VALUE rb_gc_disable _((void));
  8. VALUE rb_gc_start _((void));
  9. +VALUE rb_gc_enable_stats _((void));
  10. +VALUE rb_gc_disable_stats _((void));
  11. +VALUE rb_gc_allocated_size _((void));
  12. +unsigned long rb_os_live_objects _((void));
  13. +#ifdef HAVE_LONG_LONG
  14. +unsigned long long rb_os_allocated_objects _((void));
  15. +#else
  16. +unsigned long rb_os_allocated_objects _((void));
  17. +#endif
  18. /* hash.c */
  19. void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long));
  20. void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE));
  21. Index: gc.c
  22. ===================================================================
  23. --- gc.c (revision 20354)
  24. +++ gc.c (working copy)
  25. @@ -32,8 +32,16 @@
  26. #define EXIT_FAILURE 1
  27. #endif
  28.  
  29. +#ifdef _WIN32
  30. +#include <string.h>
  31. +#else
  32. +#include <strings.h>
  33. +#endif
  34. +
  35. #ifdef HAVE_SYS_TIME_H
  36. #include <sys/time.h>
  37. +#elif defined(_WIN32)
  38. +#include <time.h>
  39. #endif
  40.  
  41. #ifdef HAVE_SYS_RESOURCE_H
  42. @@ -52,7 +60,6 @@
  43. #ifdef __CYGWIN__
  44. int _setjmp(), _longjmp();
  45. #endif
  46. -
  47. /* Make alloca work the best possible way. */
  48. #ifdef __GNUC__
  49. # ifndef atarist
  50. @@ -90,6 +97,20 @@
  51.  
  52. int ruby_gc_stress = 0;
  53.  
  54. +static unsigned long live_objects = 0;
  55. +unsigned long rb_os_live_objects()
  56. +{ return live_objects; }
  57. +
  58. +#if defined(HAVE_LONG_LONG)
  59. +static unsigned long long allocated_objects = 0;
  60. +unsigned long long rb_os_allocated_objects()
  61. +{ return allocated_objects; }
  62. +#else
  63. +static unsigned long allocated_objects = 0;
  64. +unsigned long rb_os_allocated_objects()
  65. +{ return allocated_objects; }
  66. +#endif
  67. +
  68. NORETURN(void rb_exc_jump _((VALUE)));
  69.  
  70. void
  71. @@ -144,6 +165,10 @@
  72. return bool;
  73. }
  74.  
  75. +long gc_allocated_size = 0;
  76. +long gc_num_allocations = 0;
  77. +static int gc_statistics = 0;
  78. +
  79. void *
  80. ruby_xmalloc(size)
  81. long size;
  82. @@ -166,6 +191,10 @@
  83. rb_memerror();
  84. }
  85. }
  86. + if (gc_statistics) {
  87. + gc_allocated_size += size;
  88. + gc_num_allocations += 1;
  89. + }
  90. malloc_increase += size;
  91.  
  92. return mem;
  93. @@ -217,8 +246,16 @@
  94. RUBY_CRITICAL(free(x));
  95. }
  96.  
  97. +#if HAVE_LONG_LONG
  98. +#define GC_TIME_TYPE LONG_LONG
  99. +#else
  100. +#define GC_TIME_TYPE long
  101. +#endif
  102. +
  103. extern int ruby_in_compile;
  104. static int dont_gc;
  105. +static GC_TIME_TYPE gc_time = 0;
  106. +static int gc_collections = 0;
  107. static int during_gc;
  108. static int need_call_final = 0;
  109. static st_table *finalizer_table = 0;
  110. @@ -253,7 +290,7 @@
  111. * Disables garbage collection, returning <code>true</code> if garbage
  112. * collection was already disabled.
  113. *
  114. - * GC.disable #=> false
  115. + * GC.disable #=> false or true
  116. * GC.disable #=> true
  117. *
  118. */
  119. @@ -267,6 +304,140 @@
  120. return old;
  121. }
  122.  
  123. +/*
  124. + * call-seq:
  125. + * GC.enable_stats => true or false
  126. + *
  127. + * Enables garbage collection statistics, returning <code>true</code> if garbage
  128. + * collection statistics was already enabled.
  129. + *
  130. + * GC.enable_stats #=> false or true
  131. + * GC.enable_stats #=> true
  132. + *
  133. + */
  134. +
  135. +VALUE
  136. +rb_gc_enable_stats()
  137. +{
  138. + int old = gc_statistics;
  139. + gc_statistics = Qtrue;
  140. + return old;
  141. +}
  142. +
  143. +/*
  144. + * call-seq:
  145. + * GC.disable_stats => true or false
  146. + *
  147. + * Disables garbage collection statistics, returning <code>true</code> if garbage
  148. + * collection statistics was already disabled.
  149. + *
  150. + * GC.disable_stats #=> false or true
  151. + * GC.disable_stats #=> true
  152. + *
  153. + */
  154. +
  155. +VALUE
  156. +rb_gc_disable_stats()
  157. +{
  158. + int old = gc_statistics;
  159. + gc_statistics = Qfalse;
  160. + gc_allocated_size = 0;
  161. + gc_num_allocations = 0;
  162. + return old;
  163. +}
  164. +
  165. +/*
  166. + * call-seq:
  167. + * GC.clear_stats => nil
  168. + *
  169. + * Clears garbage collection statistics, returning nil. This resets the number
  170. + * of collections (GC.collections) and the time used (GC.time) to 0.
  171. + *
  172. + * GC.clear_stats #=> nil
  173. + *
  174. + */
  175. +
  176. +VALUE
  177. +rb_gc_clear_stats()
  178. +{
  179. + gc_collections = 0;
  180. + gc_time = 0;
  181. + gc_allocated_size = 0;
  182. + gc_num_allocations = 0;
  183. + return Qnil;
  184. +}
  185. +
  186. +/*
  187. + * call-seq:
  188. + * GC.allocated_size => Integer
  189. + *
  190. + * Returns the size of memory (in bytes) allocated since GC statistics collection
  191. + * was enabled.
  192. + *
  193. + * GC.allocated_size #=> 35
  194. + *
  195. + */
  196. +VALUE
  197. +rb_gc_allocated_size()
  198. +{
  199. + return INT2NUM(gc_allocated_size);
  200. +}
  201. +
  202. +/*
  203. + * call-seq:
  204. + * GC.num_allocations => Integer
  205. + *
  206. + * Returns the number of memory allocations since GC statistics collection
  207. + * was enabled.
  208. + *
  209. + * GC.num_allocations #=> 150
  210. + *
  211. + */
  212. +VALUE
  213. +rb_gc_num_allocations()
  214. +{
  215. + return INT2NUM(gc_num_allocations);
  216. +}
  217. +
  218. +/*
  219. + * call-seq:
  220. + * GC.collections => Integer
  221. + *
  222. + * Returns the number of garbage collections performed while GC statistics collection
  223. + * was enabled.
  224. + *
  225. + * GC.collections #=> 35
  226. + *
  227. + */
  228. +
  229. +VALUE
  230. +rb_gc_collections()
  231. +{
  232. + return INT2NUM(gc_collections);
  233. +}
  234. +
  235. +/*
  236. + * call-seq:
  237. + * GC.time => Integer
  238. + *
  239. + * Returns the time spent during garbage collection while GC statistics collection
  240. + * was enabled (in micro seconds).
  241. + *
  242. + * GC.time #=> 20000
  243. + *
  244. + */
  245. +
  246. +VALUE
  247. +rb_gc_time()
  248. +{
  249. +#if HAVE_LONG_LONG
  250. + return LL2NUM(gc_time);
  251. +#else
  252. + return LONG2NUM(gc_time);
  253. +#endif
  254. +}
  255. +
  256. +
  257. VALUE rb_mGC;
  258.  
  259. static struct gc_list {
  260. @@ -358,7 +529,7 @@
  261. static RVALUE *freelist = 0;
  262. static RVALUE *deferred_final_list = 0;
  263.  
  264. -#define HEAPS_INCREMENT 10
  265. +static int heaps_increment = 10;
  266. static struct heaps_slot {
  267. void *membase;
  268. RVALUE *slot;
  269. @@ -367,13 +538,165 @@
  270. static int heaps_length = 0;
  271. static int heaps_used = 0;
  272.  
  273. -#define HEAP_MIN_SLOTS 10000
  274. -static int heap_slots = HEAP_MIN_SLOTS;
  275. +static int heap_min_slots = 10000;
  276. +static int heap_slots = 10000;
  277.  
  278. -#define FREE_MIN 4096
  279. +static int heap_free_min = 4096;
  280. +static int heap_slots_increment = 10000;
  281. +static double heap_slots_growth_factor = 1.8;
  282.  
  283. +static long initial_malloc_limit = GC_MALLOC_LIMIT;
  284. +
  285. +static int verbose_gc_stats = Qfalse;
  286. +
  287. +static FILE* gc_data_file = NULL;
  288. +
  289. static RVALUE *himem, *lomem;
  290.  
  291. +static void set_gc_parameters()
  292. +{
  293. + char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr, *heap_slots_incr_ptr,
  294. + *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr, *heap_slots_growth_factor_ptr;
  295. +
  296. + gc_data_file = stderr;
  297. +
  298. + gc_stats_ptr = getenv("RUBY_GC_STATS");
  299. + if (gc_stats_ptr != NULL) {
  300. + int gc_stats_i = atoi(gc_stats_ptr);
  301. + if (gc_stats_i > 0) {
  302. + verbose_gc_stats = Qtrue;
  303. + }
  304. + }
  305. +
  306. + gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE");
  307. + if (gc_heap_file_ptr != NULL) {
  308. + FILE* data_file = fopen(gc_heap_file_ptr, "w");
  309. + if (data_file != NULL) {
  310. + gc_data_file = data_file;
  311. + }
  312. + else {
  313. + fprintf(stderr,
  314. + "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr);
  315. + }
  316. + }
  317. +
  318. + min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS");
  319. + if (min_slots_ptr != NULL) {
  320. + int min_slots_i = atoi(min_slots_ptr);
  321. + if (verbose_gc_stats) {
  322. + fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr);
  323. + }
  324. + if (min_slots_i > 0) {
  325. + heap_slots = min_slots_i;
  326. + heap_min_slots = min_slots_i;
  327. + }
  328. + }
  329. +
  330. + free_min_ptr = getenv("RUBY_HEAP_FREE_MIN");
  331. + if (free_min_ptr != NULL) {
  332. + int free_min_i = atoi(free_min_ptr);
  333. + if (verbose_gc_stats) {
  334. + fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr);
  335. + }
  336. + if (free_min_i > 0) {
  337. + heap_free_min = free_min_i;
  338. + }
  339. + }
  340. +
  341. + heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT");
  342. + if (heap_incr_ptr != NULL) {
  343. + int heap_incr_i = atoi(heap_incr_ptr);
  344. + if (verbose_gc_stats) {
  345. + fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr);
  346. + }
  347. + if (heap_incr_i > 0) {
  348. + heaps_increment = heap_incr_i;
  349. + }
  350. + }
  351. +
  352. + heap_slots_incr_ptr = getenv("RUBY_HEAP_SLOTS_INCREMENT");
  353. + if (heap_slots_incr_ptr != NULL) {
  354. + int heap_slots_incr_i = atoi(heap_slots_incr_ptr);
  355. + if (verbose_gc_stats) {
  356. + fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr);
  357. + }
  358. + if (heap_slots_incr_i > 0) {
  359. + heap_slots_increment = heap_slots_incr_i;
  360. + }
  361. + }
  362. +
  363. + heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR");
  364. + if (heap_slots_growth_factor_ptr != NULL) {
  365. + double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr);
  366. + if (verbose_gc_stats) {
  367. + fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr);
  368. + }
  369. + if (heap_slots_growth_factor_d > 0) {
  370. + heap_slots_growth_factor = heap_slots_growth_factor_d;
  371. + }
  372. + }
  373. +
  374. + malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT");
  375. + if (malloc_limit_ptr != NULL) {
  376. + int malloc_limit_i = atol(malloc_limit_ptr);
  377. + if (verbose_gc_stats) {
  378. + fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr);
  379. + }
  380. + if (malloc_limit_i > 0) {
  381. + initial_malloc_limit = malloc_limit_i;
  382. + }
  383. + }
  384. +}
  385. +
  386. +/*
  387. + * call-seq:
  388. + * GC.dump => nil
  389. + *
  390. + * dumps information about the current GC data structures to the GC log file
  391. + *
  392. + * GC.dump #=> nil
  393. + *
  394. + */
  395. +
  396. +VALUE
  397. +rb_gc_dump()
  398. +{
  399. + int i;
  400. +
  401. + for (i = 0; i < heaps_used; i++) {
  402. + int heap_size = heaps[i].limit;
  403. + fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size);
  404. + }
  405. +
  406. + return Qnil;
  407. +}
  408. +
  409. +/*
  410. + * call-seq:
  411. + * GC.log String => String
  412. + *
  413. + * Logs string to the GC data file and returns it.
  414. + *
  415. + * GC.log "manual GC call" #=> "manual GC call"
  416. + *
  417. + */
  418. +
  419. +VALUE
  420. +rb_gc_log(self, original_str)
  421. + VALUE self, original_str;
  422. +{
  423. + if (original_str == Qnil) {
  424. + fprintf(gc_data_file, "\n");
  425. + }
  426. + else {
  427. + VALUE str = StringValue(original_str);
  428. + char *p = RSTRING(str)->ptr;
  429. + fprintf(gc_data_file, "%s\n", p);
  430. + }
  431. + return original_str;
  432. +}
  433. +
  434. +
  435. static void
  436. add_heap()
  437. {
  438. @@ -384,7 +707,7 @@
  439. struct heaps_slot *p;
  440. int length;
  441.  
  442. - heaps_length += HEAPS_INCREMENT;
  443. + heaps_length += heaps_increment;
  444. length = heaps_length*sizeof(struct heaps_slot);
  445. RUBY_CRITICAL(
  446. if (heaps_used > 0) {
  447. @@ -400,10 +723,10 @@
  448. for (;;) {
  449. RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1)));
  450. if (p == 0) {
  451. - if (heap_slots == HEAP_MIN_SLOTS) {
  452. + if (heap_slots == heap_min_slots) {
  453. rb_memerror();
  454. }
  455. - heap_slots = HEAP_MIN_SLOTS;
  456. + heap_slots = heap_min_slots;
  457. continue;
  458. }
  459. heaps[heaps_used].membase = p;
  460. @@ -419,8 +742,9 @@
  461. if (lomem == 0 || lomem > p) lomem = p;
  462. if (himem < pend) himem = pend;
  463. heaps_used++;
  464. - heap_slots *= 1.8;
  465. - if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS;
  466. + heap_slots += heap_slots_increment;
  467. + heap_slots_increment *= heap_slots_growth_factor;
  468. + if (heap_slots <= 0) heap_slots = heap_min_slots;
  469.  
  470. while (p < pend) {
  471. p->as.free.flags = 0;
  472. @@ -454,6 +778,8 @@
  473. RANY(obj)->file = ruby_sourcefile;
  474. RANY(obj)->line = ruby_sourceline;
  475. #endif
  476. + live_objects++;
  477. + allocated_objects++;
  478. return obj;
  479. }
  480.  
  481. @@ -1115,6 +1441,39 @@
  482. }
  483. }
  484.  
  485. +static char* obj_type(int tp)
  486. +{
  487. + switch (tp) {
  488. + case T_NIL : return "NIL";
  489. + case T_OBJECT : return "OBJECT";
  490. + case T_CLASS : return "CLASS";
  491. + case T_ICLASS : return "ICLASS";
  492. + case T_MODULE : return "MODULE";
  493. + case T_FLOAT : return "FLOAT";
  494. + case T_STRING : return "STRING";
  495. + case T_REGEXP : return "REGEXP";
  496. + case T_ARRAY : return "ARRAY";
  497. + case T_FIXNUM : return "FIXNUM";
  498. + case T_HASH : return "HASH";
  499. + case T_STRUCT : return "STRUCT";
  500. + case T_BIGNUM : return "BIGNUM";
  501. + case T_FILE : return "FILE";
  502. +
  503. + case T_TRUE : return "TRUE";
  504. + case T_FALSE : return "FALSE";
  505. + case T_DATA : return "DATA";
  506. + case T_MATCH : return "MATCH";
  507. + case T_SYMBOL : return "SYMBOL";
  508. +
  509. + case T_BLKTAG : return "BLKTAG";
  510. + case T_UNDEF : return "UNDEF";
  511. + case T_VARMAP : return "VARMAP";
  512. + case T_SCOPE : return "SCOPE";
  513. + case T_NODE : return "NODE";
  514. + default: return "____";
  515. + }
  516. +}
  517. +
  518. static void
  519. free_unused_heaps()
  520. {
  521. @@ -1144,14 +1503,24 @@
  522. int i;
  523. unsigned long live = 0;
  524. unsigned long free_min = 0;
  525. + live_objects = 0;
  526.  
  527. + unsigned long really_freed = 0;
  528. + int free_counts[256];
  529. + int live_counts[256];
  530. + int do_gc_stats = gc_statistics & verbose_gc_stats;
  531. +
  532. for (i = 0; i < heaps_used; i++) {
  533. free_min += heaps[i].limit;
  534. }
  535. free_min = free_min * 0.2;
  536. - if (free_min < FREE_MIN)
  537. - free_min = FREE_MIN;
  538. + if (free_min < heap_free_min)
  539. + free_min = heap_free_min;
  540.  
  541. + if (do_gc_stats) {
  542. + for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; }
  543. + }
  544. +
  545. if (ruby_in_compile && ruby_parser_stack_on_heap()) {
  546. /* should not reclaim nodes during compilation
  547. if yacc's semantic stack is not allocated on machine stack */
  548. @@ -1188,12 +1557,20 @@
  549. if (!deferred) {
  550. p->as.free.flags = T_ZOMBIE;
  551. RDATA(p)->dfree = 0;
  552. + } else if (do_gc_stats) {
  553. + really_freed++;
  554. }
  555. p->as.free.flags |= FL_MARK;
  556. p->as.free.next = final_list;
  557. final_list = p;
  558. }
  559. else {
  560. + if (do_gc_stats) {
  561. + int obt = p->as.basic.flags & T_MASK;
  562. + if (obt) {
  563. + free_counts[obt]++;
  564. + }
  565. + }
  566. add_freelist(p);
  567. }
  568. n++;
  569. @@ -1204,7 +1581,10 @@
  570. }
  571. else {
  572. RBASIC(p)->flags &= ~FL_MARK;
  573. - live++;
  574. + live_objects++;
  575. + if (do_gc_stats) {
  576. + live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++;
  577. + }
  578. }
  579. p++;
  580. }
  581. @@ -1222,8 +1602,8 @@
  582. }
  583. }
  584. if (malloc_increase > malloc_limit) {
  585. - malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
  586. - if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
  587. + malloc_limit += (malloc_increase - malloc_limit) * (double)live_objects / (live_objects + freed);
  588. + if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit;
  589. }
  590. malloc_increase = 0;
  591. if (freed < free_min) {
  592. @@ -1231,6 +1611,20 @@
  593. }
  594. during_gc = 0;
  595.  
  596. + if (do_gc_stats) {
  597. + fprintf(gc_data_file, "objects processed: %.7d\n", live+freed);
  598. + fprintf(gc_data_file, "live objects : %.7d\n", live);
  599. + fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed);
  600. + fprintf(gc_data_file, "freed objects : %.7d\n", really_freed);
  601. + for(i=0; i<256; i++) {
  602. + if (free_counts[i]>0) {
  603. + fprintf(gc_data_file,
  604. + "kept %.7d / freed %.7d objects of type %s\n",
  605. + live_counts[i], free_counts[i], obj_type(i));
  606. + }
  607. + }
  608. + }
  609. +
  610. /* clear finalization list */
  611. if (final_list) {
  612. deferred_final_list = final_list;
  613. @@ -1434,6 +1828,7 @@
  614. struct gc_list *list;
  615. struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */
  616. jmp_buf save_regs_gc_mark;
  617. + struct timeval gctv1, gctv2;
  618. SET_STACK_END;
  619.  
  620. #ifdef HAVE_NATIVETHREAD
  621. @@ -1450,6 +1845,14 @@
  622. if (during_gc) return;
  623. during_gc++;
  624.  
  625. + if (gc_statistics) {
  626. + gc_collections++;
  627. + gettimeofday(&gctv1, NULL);
  628. + if (verbose_gc_stats) {
  629. + fprintf(gc_data_file, "Garbage collection started\n");
  630. + }
  631. + }
  632. +
  633. init_mark_stack();
  634.  
  635. gc_mark((VALUE)ruby_current_node, 0);
  636. @@ -1525,6 +1928,17 @@
  637. } while (!MARK_STACK_EMPTY);
  638.  
  639. gc_sweep();
  640. +
  641. + if (gc_statistics) {
  642. + GC_TIME_TYPE musecs_used;
  643. + gettimeofday(&gctv2, NULL);
  644. + musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec);
  645. + gc_time += musecs_used;
  646. +
  647. + if (verbose_gc_stats) {
  648. + fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000);
  649. + }
  650. + }
  651. }
  652.  
  653. void
  654. @@ -1706,6 +2120,7 @@
  655. if (!rb_gc_stack_start) {
  656. Init_stack(0);
  657. }
  658. + set_gc_parameters();
  659. add_heap();
  660. }
  661.  
  662. @@ -2139,6 +2554,35 @@
  663. return (VALUE)((long)obj|FIXNUM_FLAG);
  664. }
  665.  
  666. +/* call-seq:
  667. + * ObjectSpace.live_objects => number
  668. + *
  669. + * Returns the count of objects currently allocated in the system. This goes
  670. + * down after the garbage collector runs.
  671. + */
  672. +static
  673. +VALUE os_live_objects(VALUE self)
  674. +{ return ULONG2NUM(live_objects); }
  675. +
  676. +/* call-seq:
  677. + * ObjectSpace.allocated_objects => number
  678. + *
  679. + * Returns the count of objects allocated since the Ruby interpreter has
  680. + * started. This number can only increase. To know how many objects are
  681. + * currently allocated, use ObjectSpace::live_objects
  682. + */
  683. +static
  684. +VALUE os_allocated_objects(VALUE self)
  685. +{
  686. +#if defined(HAVE_LONG_LONG)
  687. + return ULL2NUM(allocated_objects);
  688. +#else
  689. + return ULONG2NUM(allocated_objects);
  690. +#endif
  691. +}
  692. +
  693. +
  694. +
  695. /*
  696. * The <code>GC</code> module provides an interface to Ruby's mark and
  697. * sweep garbage collection mechanism. Some of the underlying methods
  698. @@ -2158,6 +2602,16 @@
  699. rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1);
  700. rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
  701.  
  702. + rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0);
  703. + rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0);
  704. + rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0);
  705. + rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0);
  706. + rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0);
  707. + rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0);
  708. + rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0);
  709. + rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0);
  710. + rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1);
  711. +
  712. rb_mObSpace = rb_define_module("ObjectSpace");
  713. rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);
  714. rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0);
  715. @@ -2165,6 +2619,8 @@
  716. rb_define_module_function(rb_mObSpace, "remove_finalizer", rm_final, 1);
  717. rb_define_module_function(rb_mObSpace, "finalizers", finals, 0);
  718. rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1);
  719. + rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0);
  720. + rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0);
  721.  
  722. rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1);
  723. rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1);
Add Comment
Please, Sign In to add comment