Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /********************************************************************** 00002 00003 objspace.c - ObjectSpace extender for MRI. 00004 00005 $Author: ktsj $ 00006 created at: Wed Jun 17 07:39:17 2009 00007 00008 NOTE: This extension library is not expected to exist except C Ruby. 00009 00010 All the files in this distribution are covered under the Ruby's 00011 license (see the file COPYING). 00012 00013 **********************************************************************/ 00014 00015 /* objspace library extends ObjectSpace module and add several 00016 * methods to get internal statistic information about 00017 * object/memory management. 00018 * 00019 * Generally, you *SHOULD NOT*use this library if you do not know 00020 * about the MRI implementation. Mainly, this library is for (memory) 00021 * profiler developers and MRI developers who need to know how MRI 00022 * memory usage. 00023 * 00024 */ 00025 00026 #include <ruby/ruby.h> 00027 #include <ruby/st.h> 00028 #include <ruby/io.h> 00029 #include <ruby/re.h> 00030 #include "node.h" 00031 #include "gc.h" 00032 #include "regint.h" 00033 #include "internal.h" 00034 00035 size_t rb_str_memsize(VALUE); 00036 size_t rb_ary_memsize(VALUE); 00037 size_t rb_io_memsize(const rb_io_t *); 00038 size_t rb_generic_ivar_memsize(VALUE); 00039 size_t rb_objspace_data_type_memsize(VALUE obj); 00040 00041 static size_t 00042 memsize_of(VALUE obj) 00043 { 00044 size_t size = 0; 00045 00046 if (SPECIAL_CONST_P(obj)) { 00047 return 0; 00048 } 00049 00050 if (FL_TEST(obj, FL_EXIVAR)) { 00051 size += rb_generic_ivar_memsize(obj); 00052 } 00053 00054 switch (BUILTIN_TYPE(obj)) { 00055 case T_OBJECT: 00056 if (!(RBASIC(obj)->flags & ROBJECT_EMBED) && 00057 ROBJECT(obj)->as.heap.ivptr) { 00058 size += ROBJECT(obj)->as.heap.numiv * sizeof(VALUE); 00059 } 00060 break; 00061 case T_MODULE: 00062 case T_CLASS: 00063 size += st_memsize(RCLASS_M_TBL(obj)); 00064 if (RCLASS_IV_TBL(obj)) { 00065 size += st_memsize(RCLASS_IV_TBL(obj)); 00066 } 00067 if (RCLASS_IV_INDEX_TBL(obj)) { 00068 size += st_memsize(RCLASS_IV_INDEX_TBL(obj)); 00069 } 00070 if (RCLASS(obj)->ptr->iv_tbl) { 00071 size += st_memsize(RCLASS(obj)->ptr->iv_tbl); 00072 } 00073 if (RCLASS(obj)->ptr->const_tbl) { 00074 size += st_memsize(RCLASS(obj)->ptr->const_tbl); 00075 } 00076 size += sizeof(rb_classext_t); 00077 break; 00078 case T_STRING: 00079 size += rb_str_memsize(obj); 00080 break; 00081 case T_ARRAY: 00082 size += rb_ary_memsize(obj); 00083 break; 00084 case T_HASH: 00085 if (RHASH(obj)->ntbl) { 00086 size += st_memsize(RHASH(obj)->ntbl); 00087 } 00088 break; 00089 case T_REGEXP: 00090 if (RREGEXP(obj)->ptr) { 00091 size += onig_memsize(RREGEXP(obj)->ptr); 00092 } 00093 break; 00094 case T_DATA: 00095 size += rb_objspace_data_type_memsize(obj); 00096 break; 00097 case T_MATCH: 00098 if (RMATCH(obj)->rmatch) { 00099 struct rmatch *rm = RMATCH(obj)->rmatch; 00100 size += sizeof(struct re_registers); /* TODO: onig_region_memsize(&rm->regs); */ 00101 size += sizeof(struct rmatch_offset) * rm->char_offset_num_allocated; 00102 size += sizeof(struct rmatch); 00103 } 00104 break; 00105 case T_FILE: 00106 if (RFILE(obj)->fptr) { 00107 size += rb_io_memsize(RFILE(obj)->fptr); 00108 } 00109 break; 00110 case T_RATIONAL: 00111 case T_COMPLEX: 00112 break; 00113 case T_ICLASS: 00114 /* iClass shares table with the module */ 00115 break; 00116 00117 case T_FLOAT: 00118 break; 00119 00120 case T_BIGNUM: 00121 if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) { 00122 size += RBIGNUM_LEN(obj) * sizeof(BDIGIT); 00123 } 00124 break; 00125 case T_NODE: 00126 switch (nd_type(obj)) { 00127 case NODE_SCOPE: 00128 if (RNODE(obj)->u1.tbl) { 00129 /* TODO: xfree(RANY(obj)->as.node.u1.tbl); */ 00130 } 00131 break; 00132 case NODE_ALLOCA: 00133 /* TODO: xfree(RANY(obj)->as.node.u1.node); */ 00134 ; 00135 } 00136 break; /* no need to free iv_tbl */ 00137 00138 case T_STRUCT: 00139 if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 && 00140 RSTRUCT(obj)->as.heap.ptr) { 00141 size += sizeof(VALUE) * RSTRUCT_LEN(obj); 00142 } 00143 break; 00144 00145 case T_ZOMBIE: 00146 break; 00147 00148 default: 00149 rb_bug("objspace/memsize_of(): unknown data type 0x%x(%p)", 00150 BUILTIN_TYPE(obj), (void*)obj); 00151 } 00152 00153 return size; 00154 } 00155 00156 /* 00157 * call-seq: 00158 * ObjectSpace.memsize_of(obj) -> Integer 00159 * 00160 * Return consuming memory size of obj. 00161 * 00162 * Note that the return size is incomplete. You need to deal with 00163 * this information as only a *HINT*. Especially, the size of 00164 * T_DATA may not be correct. 00165 * 00166 * This method is not expected to work except C Ruby. 00167 */ 00168 00169 static VALUE 00170 memsize_of_m(VALUE self, VALUE obj) 00171 { 00172 return SIZET2NUM(memsize_of(obj)); 00173 } 00174 00175 struct total_data { 00176 size_t total; 00177 VALUE klass; 00178 }; 00179 00180 static int 00181 total_i(void *vstart, void *vend, size_t stride, void *ptr) 00182 { 00183 VALUE v; 00184 struct total_data *data = (struct total_data *)ptr; 00185 00186 for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) { 00187 if (RBASIC(v)->flags) { 00188 switch (BUILTIN_TYPE(v)) { 00189 case T_NONE: 00190 case T_ICLASS: 00191 case T_NODE: 00192 case T_ZOMBIE: 00193 continue; 00194 case T_CLASS: 00195 if (FL_TEST(v, FL_SINGLETON)) 00196 continue; 00197 default: 00198 if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) { 00199 data->total += memsize_of(v); 00200 } 00201 } 00202 } 00203 } 00204 00205 return 0; 00206 } 00207 00208 /* 00209 * call-seq: 00210 * ObjectSpace.memsize_of_all([klass]) -> Integer 00211 * 00212 * Return consuming memory size of all living objects. 00213 * If klass (should be Class object) is given, return the total 00214 * memory size of instances of the given class. 00215 * 00216 * Note that the returned size is incomplete. You need to deal with 00217 * this information as only a *HINT*. Especially, the size of 00218 * T_DATA may not be correct. 00219 * 00220 * Note that this method does *NOT* return total malloc'ed memory size. 00221 * 00222 * This method can be defined by the following Ruby code: 00223 * 00224 * def memsize_of_all klass = false 00225 * total = 0 00226 * ObjectSpace.each_objects{|e| 00227 * total += ObjectSpace.memsize_of(e) if klass == false || e.kind_of?(klass) 00228 * } 00229 * total 00230 * end 00231 * 00232 * This method is not expected to work except C Ruby. 00233 */ 00234 00235 static VALUE 00236 memsize_of_all_m(int argc, VALUE *argv, VALUE self) 00237 { 00238 struct total_data data = {0, 0}; 00239 00240 if (argc > 0) { 00241 rb_scan_args(argc, argv, "01", &data.klass); 00242 } 00243 00244 rb_objspace_each_objects(total_i, &data); 00245 return SIZET2NUM(data.total); 00246 } 00247 00248 static int 00249 set_zero_i(st_data_t key, st_data_t val, st_data_t arg) 00250 { 00251 VALUE k = (VALUE)key; 00252 VALUE hash = (VALUE)arg; 00253 rb_hash_aset(hash, k, INT2FIX(0)); 00254 return ST_CONTINUE; 00255 } 00256 00257 static int 00258 cos_i(void *vstart, void *vend, size_t stride, void *data) 00259 { 00260 size_t *counts = (size_t *)data; 00261 VALUE v = (VALUE)vstart; 00262 00263 for (;v != (VALUE)vend; v += stride) { 00264 if (RBASIC(v)->flags) { 00265 counts[BUILTIN_TYPE(v)] += memsize_of(v); 00266 } 00267 } 00268 return 0; 00269 } 00270 00271 /* 00272 * call-seq: 00273 * ObjectSpace.count_objects_size([result_hash]) -> hash 00274 * 00275 * Counts objects size (in bytes) for each type. 00276 * 00277 * Note that this information is incomplete. You need to deal with 00278 * this information as only a *HINT*. Especially, total size of 00279 * T_DATA may not right size. 00280 * 00281 * It returns a hash as: 00282 * {:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...} 00283 * 00284 * If the optional argument, result_hash, is given, 00285 * it is overwritten and returned. 00286 * This is intended to avoid probe effect. 00287 * 00288 * The contents of the returned hash is implementation defined. 00289 * It may be changed in future. 00290 * 00291 * This method is not expected to work except C Ruby. 00292 */ 00293 00294 static VALUE 00295 count_objects_size(int argc, VALUE *argv, VALUE os) 00296 { 00297 size_t counts[T_MASK+1]; 00298 size_t total = 0; 00299 size_t i; 00300 VALUE hash; 00301 00302 if (rb_scan_args(argc, argv, "01", &hash) == 1) { 00303 if (TYPE(hash) != T_HASH) 00304 rb_raise(rb_eTypeError, "non-hash given"); 00305 } 00306 00307 for (i = 0; i <= T_MASK; i++) { 00308 counts[i] = 0; 00309 } 00310 00311 rb_objspace_each_objects(cos_i, &counts[0]); 00312 00313 if (hash == Qnil) { 00314 hash = rb_hash_new(); 00315 } 00316 else if (!RHASH_EMPTY_P(hash)) { 00317 st_foreach(RHASH_TBL(hash), set_zero_i, hash); 00318 } 00319 00320 for (i = 0; i <= T_MASK; i++) { 00321 if (counts[i]) { 00322 VALUE type; 00323 switch (i) { 00324 #define COUNT_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break; 00325 COUNT_TYPE(T_NONE); 00326 COUNT_TYPE(T_OBJECT); 00327 COUNT_TYPE(T_CLASS); 00328 COUNT_TYPE(T_MODULE); 00329 COUNT_TYPE(T_FLOAT); 00330 COUNT_TYPE(T_STRING); 00331 COUNT_TYPE(T_REGEXP); 00332 COUNT_TYPE(T_ARRAY); 00333 COUNT_TYPE(T_HASH); 00334 COUNT_TYPE(T_STRUCT); 00335 COUNT_TYPE(T_BIGNUM); 00336 COUNT_TYPE(T_FILE); 00337 COUNT_TYPE(T_DATA); 00338 COUNT_TYPE(T_MATCH); 00339 COUNT_TYPE(T_COMPLEX); 00340 COUNT_TYPE(T_RATIONAL); 00341 COUNT_TYPE(T_NIL); 00342 COUNT_TYPE(T_TRUE); 00343 COUNT_TYPE(T_FALSE); 00344 COUNT_TYPE(T_SYMBOL); 00345 COUNT_TYPE(T_FIXNUM); 00346 COUNT_TYPE(T_UNDEF); 00347 COUNT_TYPE(T_NODE); 00348 COUNT_TYPE(T_ICLASS); 00349 COUNT_TYPE(T_ZOMBIE); 00350 #undef COUNT_TYPE 00351 default: type = INT2NUM(i); break; 00352 } 00353 total += counts[i]; 00354 rb_hash_aset(hash, type, SIZET2NUM(counts[i])); 00355 } 00356 } 00357 rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total)); 00358 return hash; 00359 } 00360 00361 static int 00362 cn_i(void *vstart, void *vend, size_t stride, void *n) 00363 { 00364 size_t *nodes = (size_t *)n; 00365 VALUE v = (VALUE)vstart; 00366 00367 for (; v != (VALUE)vend; v += stride) { 00368 if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_NODE) { 00369 size_t s = nd_type((NODE *)v); 00370 nodes[s]++; 00371 } 00372 } 00373 00374 return 0; 00375 } 00376 00377 /* 00378 * call-seq: 00379 * ObjectSpace.count_nodes([result_hash]) -> hash 00380 * 00381 * Counts nodes for each node type. 00382 * 00383 * This method is not for ordinary Ruby programmers, but for MRI developers 00384 * who have interest in MRI performance and memory usage. 00385 * 00386 * It returns a hash as: 00387 * {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...} 00388 * 00389 * If the optional argument, result_hash, is given, 00390 * it is overwritten and returned. 00391 * This is intended to avoid probe effect. 00392 * 00393 * The contents of the returned hash is implementation defined. 00394 * It may be changed in future. 00395 * 00396 * This method is not expected to work except C Ruby. 00397 */ 00398 00399 static VALUE 00400 count_nodes(int argc, VALUE *argv, VALUE os) 00401 { 00402 size_t nodes[NODE_LAST+1]; 00403 size_t i; 00404 VALUE hash; 00405 00406 if (rb_scan_args(argc, argv, "01", &hash) == 1) { 00407 if (TYPE(hash) != T_HASH) 00408 rb_raise(rb_eTypeError, "non-hash given"); 00409 } 00410 00411 for (i = 0; i <= NODE_LAST; i++) { 00412 nodes[i] = 0; 00413 } 00414 00415 rb_objspace_each_objects(cn_i, &nodes[0]); 00416 00417 if (hash == Qnil) { 00418 hash = rb_hash_new(); 00419 } 00420 else if (!RHASH_EMPTY_P(hash)) { 00421 st_foreach(RHASH_TBL(hash), set_zero_i, hash); 00422 } 00423 00424 for (i=0; i<NODE_LAST; i++) { 00425 if (nodes[i] != 0) { 00426 VALUE node; 00427 switch (i) { 00428 #define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); break; 00429 COUNT_NODE(NODE_SCOPE); 00430 COUNT_NODE(NODE_BLOCK); 00431 COUNT_NODE(NODE_IF); 00432 COUNT_NODE(NODE_CASE); 00433 COUNT_NODE(NODE_WHEN); 00434 COUNT_NODE(NODE_OPT_N); 00435 COUNT_NODE(NODE_WHILE); 00436 COUNT_NODE(NODE_UNTIL); 00437 COUNT_NODE(NODE_ITER); 00438 COUNT_NODE(NODE_FOR); 00439 COUNT_NODE(NODE_BREAK); 00440 COUNT_NODE(NODE_NEXT); 00441 COUNT_NODE(NODE_REDO); 00442 COUNT_NODE(NODE_RETRY); 00443 COUNT_NODE(NODE_BEGIN); 00444 COUNT_NODE(NODE_RESCUE); 00445 COUNT_NODE(NODE_RESBODY); 00446 COUNT_NODE(NODE_ENSURE); 00447 COUNT_NODE(NODE_AND); 00448 COUNT_NODE(NODE_OR); 00449 COUNT_NODE(NODE_MASGN); 00450 COUNT_NODE(NODE_LASGN); 00451 COUNT_NODE(NODE_DASGN); 00452 COUNT_NODE(NODE_DASGN_CURR); 00453 COUNT_NODE(NODE_GASGN); 00454 COUNT_NODE(NODE_IASGN); 00455 COUNT_NODE(NODE_IASGN2); 00456 COUNT_NODE(NODE_CDECL); 00457 COUNT_NODE(NODE_CVASGN); 00458 COUNT_NODE(NODE_CVDECL); 00459 COUNT_NODE(NODE_OP_ASGN1); 00460 COUNT_NODE(NODE_OP_ASGN2); 00461 COUNT_NODE(NODE_OP_ASGN_AND); 00462 COUNT_NODE(NODE_OP_ASGN_OR); 00463 COUNT_NODE(NODE_CALL); 00464 COUNT_NODE(NODE_FCALL); 00465 COUNT_NODE(NODE_VCALL); 00466 COUNT_NODE(NODE_SUPER); 00467 COUNT_NODE(NODE_ZSUPER); 00468 COUNT_NODE(NODE_ARRAY); 00469 COUNT_NODE(NODE_ZARRAY); 00470 COUNT_NODE(NODE_VALUES); 00471 COUNT_NODE(NODE_HASH); 00472 COUNT_NODE(NODE_RETURN); 00473 COUNT_NODE(NODE_YIELD); 00474 COUNT_NODE(NODE_LVAR); 00475 COUNT_NODE(NODE_DVAR); 00476 COUNT_NODE(NODE_GVAR); 00477 COUNT_NODE(NODE_IVAR); 00478 COUNT_NODE(NODE_CONST); 00479 COUNT_NODE(NODE_CVAR); 00480 COUNT_NODE(NODE_NTH_REF); 00481 COUNT_NODE(NODE_BACK_REF); 00482 COUNT_NODE(NODE_MATCH); 00483 COUNT_NODE(NODE_MATCH2); 00484 COUNT_NODE(NODE_MATCH3); 00485 COUNT_NODE(NODE_LIT); 00486 COUNT_NODE(NODE_STR); 00487 COUNT_NODE(NODE_DSTR); 00488 COUNT_NODE(NODE_XSTR); 00489 COUNT_NODE(NODE_DXSTR); 00490 COUNT_NODE(NODE_EVSTR); 00491 COUNT_NODE(NODE_DREGX); 00492 COUNT_NODE(NODE_DREGX_ONCE); 00493 COUNT_NODE(NODE_ARGS); 00494 COUNT_NODE(NODE_ARGS_AUX); 00495 COUNT_NODE(NODE_OPT_ARG); 00496 COUNT_NODE(NODE_POSTARG); 00497 COUNT_NODE(NODE_ARGSCAT); 00498 COUNT_NODE(NODE_ARGSPUSH); 00499 COUNT_NODE(NODE_SPLAT); 00500 COUNT_NODE(NODE_TO_ARY); 00501 COUNT_NODE(NODE_BLOCK_ARG); 00502 COUNT_NODE(NODE_BLOCK_PASS); 00503 COUNT_NODE(NODE_DEFN); 00504 COUNT_NODE(NODE_DEFS); 00505 COUNT_NODE(NODE_ALIAS); 00506 COUNT_NODE(NODE_VALIAS); 00507 COUNT_NODE(NODE_UNDEF); 00508 COUNT_NODE(NODE_CLASS); 00509 COUNT_NODE(NODE_MODULE); 00510 COUNT_NODE(NODE_SCLASS); 00511 COUNT_NODE(NODE_COLON2); 00512 COUNT_NODE(NODE_COLON3); 00513 COUNT_NODE(NODE_DOT2); 00514 COUNT_NODE(NODE_DOT3); 00515 COUNT_NODE(NODE_FLIP2); 00516 COUNT_NODE(NODE_FLIP3); 00517 COUNT_NODE(NODE_SELF); 00518 COUNT_NODE(NODE_NIL); 00519 COUNT_NODE(NODE_TRUE); 00520 COUNT_NODE(NODE_FALSE); 00521 COUNT_NODE(NODE_ERRINFO); 00522 COUNT_NODE(NODE_DEFINED); 00523 COUNT_NODE(NODE_POSTEXE); 00524 COUNT_NODE(NODE_ALLOCA); 00525 COUNT_NODE(NODE_BMETHOD); 00526 COUNT_NODE(NODE_MEMO); 00527 COUNT_NODE(NODE_IFUNC); 00528 COUNT_NODE(NODE_DSYM); 00529 COUNT_NODE(NODE_ATTRASGN); 00530 COUNT_NODE(NODE_PRELUDE); 00531 COUNT_NODE(NODE_LAMBDA); 00532 COUNT_NODE(NODE_OPTBLOCK); 00533 #undef COUNT_NODE 00534 default: node = INT2FIX(nodes[i]); 00535 } 00536 rb_hash_aset(hash, node, SIZET2NUM(nodes[i])); 00537 } 00538 } 00539 return hash; 00540 } 00541 00542 static int 00543 cto_i(void *vstart, void *vend, size_t stride, void *data) 00544 { 00545 VALUE hash = (VALUE)data; 00546 VALUE v = (VALUE)vstart; 00547 00548 for (; v != (VALUE)vend; v += stride) { 00549 if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_DATA) { 00550 VALUE counter; 00551 VALUE key = RBASIC(v)->klass; 00552 00553 if (key == 0) { 00554 const char *name = rb_objspace_data_type_name(v); 00555 if (name == 0) name = "unknown"; 00556 key = ID2SYM(rb_intern(name)); 00557 } 00558 00559 counter = rb_hash_aref(hash, key); 00560 if (NIL_P(counter)) { 00561 counter = INT2FIX(1); 00562 } 00563 else { 00564 counter = INT2FIX(FIX2INT(counter) + 1); 00565 } 00566 00567 rb_hash_aset(hash, key, counter); 00568 } 00569 } 00570 00571 return 0; 00572 } 00573 00574 /* 00575 * call-seq: 00576 * ObjectSpace.count_tdata_objects([result_hash]) -> hash 00577 * 00578 * Counts objects for each T_DATA type. 00579 * 00580 * This method is not for ordinary Ruby programmers, but for MRI developers 00581 * who interest on MRI performance. 00582 * 00583 * It returns a hash as: 00584 * {RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6, 00585 * :mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99, 00586 * ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1, 00587 * Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2} 00588 * # T_DATA objects existing at startup on r32276. 00589 * 00590 * If the optional argument, result_hash, is given, 00591 * it is overwritten and returned. 00592 * This is intended to avoid probe effect. 00593 * 00594 * The contents of the returned hash is implementation defined. 00595 * It may be changed in future. 00596 * 00597 * In this version, keys are Class object or Symbol object. 00598 * If object is kind of normal (accessible) object, the key is Class object. 00599 * If object is not a kind of normal (internal) object, the key is symbol 00600 * name, registered by rb_data_type_struct. 00601 * 00602 * This method is not expected to work except C Ruby. 00603 * 00604 */ 00605 00606 static VALUE 00607 count_tdata_objects(int argc, VALUE *argv, VALUE self) 00608 { 00609 VALUE hash; 00610 00611 if (rb_scan_args(argc, argv, "01", &hash) == 1) { 00612 if (TYPE(hash) != T_HASH) 00613 rb_raise(rb_eTypeError, "non-hash given"); 00614 } 00615 00616 if (hash == Qnil) { 00617 hash = rb_hash_new(); 00618 } 00619 else if (!RHASH_EMPTY_P(hash)) { 00620 st_foreach(RHASH_TBL(hash), set_zero_i, hash); 00621 } 00622 00623 rb_objspace_each_objects(cto_i, (void *)hash); 00624 00625 return hash; 00626 } 00627 00628 /* objspace library extends ObjectSpace module and add several 00629 * methods to get internal statistic information about 00630 * object/memory management. 00631 * 00632 * Generally, you *SHOULD NOT*use this library if you do not know 00633 * about the MRI implementation. Mainly, this library is for (memory) 00634 * profiler developers and MRI developers who need to know how MRI 00635 * memory usage. 00636 */ 00637 00638 void 00639 Init_objspace(void) 00640 { 00641 VALUE rb_mObjSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace")); 00642 00643 rb_define_module_function(rb_mObjSpace, "memsize_of", memsize_of_m, 1); 00644 rb_define_module_function(rb_mObjSpace, "memsize_of_all", 00645 memsize_of_all_m, -1); 00646 00647 rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1); 00648 rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1); 00649 rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1); 00650 } 00651