Ruby
1.9.3p448(2013-06-27revision41675)
Main Page
Modules
Data Structures
Files
File List
Globals
ext
objspace
objspace.c
Go to the documentation of this file.
1
/**********************************************************************
2
3
objspace.c - ObjectSpace extender for MRI.
4
5
$Author: usa $
6
created at: Wed Jun 17 07:39:17 2009
7
8
NOTE: This extension library is not expected to exist except C Ruby.
9
10
All the files in this distribution are covered under the Ruby's
11
license (see the file COPYING).
12
13
**********************************************************************/
14
15
/* objspace library extends ObjectSpace module and add several
16
* methods to get internal statistic information about
17
* object/memory management.
18
*
19
* Generally, you *SHOULD NOT*use this library if you do not know
20
* about the MRI implementation. Mainly, this library is for (memory)
21
* profiler developers and MRI developers who need to know how MRI
22
* memory usage.
23
*
24
*/
25
26
#include <
ruby/ruby.h
>
27
#include <
ruby/st.h
>
28
#include <
ruby/io.h
>
29
#include <
ruby/re.h
>
30
#include "
node.h
"
31
#include "
gc.h
"
32
#include "
regint.h
"
33
#include "
internal.h
"
34
35
size_t
rb_str_memsize
(
VALUE
);
36
size_t
rb_ary_memsize
(
VALUE
);
37
size_t
rb_io_memsize
(
const
rb_io_t
*);
38
size_t
rb_generic_ivar_memsize
(
VALUE
);
39
size_t
rb_objspace_data_type_memsize
(
VALUE
obj);
40
41
static
size_t
42
memsize_of
(
VALUE
obj)
43
{
44
size_t
size
= 0;
45
46
if
(
SPECIAL_CONST_P
(obj)) {
47
return
0;
48
}
49
50
if
(
FL_TEST
(obj,
FL_EXIVAR
)) {
51
size +=
rb_generic_ivar_memsize
(obj);
52
}
53
54
switch
(
BUILTIN_TYPE
(obj)) {
55
case
T_OBJECT
:
56
if
(!(
RBASIC
(obj)->flags &
ROBJECT_EMBED
) &&
57
ROBJECT
(obj)->as.heap.ivptr) {
58
size +=
ROBJECT
(obj)->as.heap.numiv *
sizeof
(
VALUE
);
59
}
60
break
;
61
case
T_MODULE
:
62
case
T_CLASS
:
63
size +=
st_memsize
(
RCLASS_M_TBL
(obj));
64
if
(
RCLASS_IV_TBL
(obj)) {
65
size +=
st_memsize
(
RCLASS_IV_TBL
(obj));
66
}
67
if
(
RCLASS_IV_INDEX_TBL
(obj)) {
68
size +=
st_memsize
(
RCLASS_IV_INDEX_TBL
(obj));
69
}
70
if
(
RCLASS
(obj)->ptr->iv_tbl) {
71
size +=
st_memsize
(
RCLASS
(obj)->ptr->iv_tbl);
72
}
73
if
(
RCLASS
(obj)->ptr->const_tbl) {
74
size +=
st_memsize
(
RCLASS
(obj)->ptr->const_tbl);
75
}
76
size +=
sizeof
(
rb_classext_t
);
77
break
;
78
case
T_STRING
:
79
size +=
rb_str_memsize
(obj);
80
break
;
81
case
T_ARRAY
:
82
size +=
rb_ary_memsize
(obj);
83
break
;
84
case
T_HASH
:
85
if
(
RHASH
(obj)->ntbl) {
86
size +=
st_memsize
(
RHASH
(obj)->ntbl);
87
}
88
break
;
89
case
T_REGEXP
:
90
if
(
RREGEXP
(obj)->ptr) {
91
size +=
onig_memsize
(
RREGEXP
(obj)->ptr);
92
}
93
break
;
94
case
T_DATA
:
95
size +=
rb_objspace_data_type_memsize
(obj);
96
break
;
97
case
T_MATCH
:
98
if
(
RMATCH
(obj)->
rmatch
) {
99
struct
rmatch
*rm =
RMATCH
(obj)->rmatch;
100
size +=
sizeof
(
struct
re_registers
);
/* TODO: onig_region_memsize(&rm->regs); */
101
size +=
sizeof
(
struct
rmatch_offset
) * rm->
char_offset_num_allocated
;
102
size +=
sizeof
(
struct
rmatch
);
103
}
104
break
;
105
case
T_FILE
:
106
if
(
RFILE
(obj)->fptr) {
107
size +=
rb_io_memsize
(
RFILE
(obj)->fptr);
108
}
109
break
;
110
case
T_RATIONAL
:
111
case
T_COMPLEX
:
112
break
;
113
case
T_ICLASS
:
114
/* iClass shares table with the module */
115
break
;
116
117
case
T_FLOAT
:
118
break
;
119
120
case
T_BIGNUM
:
121
if
(!(
RBASIC
(obj)->flags &
RBIGNUM_EMBED_FLAG
) &&
RBIGNUM_DIGITS
(obj)) {
122
size +=
RBIGNUM_LEN
(obj) *
sizeof
(
BDIGIT
);
123
}
124
break
;
125
case
T_NODE
:
126
switch
(
nd_type
(obj)) {
127
case
NODE_SCOPE
:
128
if
(
RNODE
(obj)->u1.tbl) {
129
/* TODO: xfree(RANY(obj)->as.node.u1.tbl); */
130
}
131
break
;
132
case
NODE_ALLOCA
:
133
/* TODO: xfree(RANY(obj)->as.node.u1.node); */
134
;
135
}
136
break
;
/* no need to free iv_tbl */
137
138
case
T_STRUCT
:
139
if
((
RBASIC
(obj)->flags &
RSTRUCT_EMBED_LEN_MASK
) == 0 &&
140
RSTRUCT
(obj)->as.heap.ptr) {
141
size +=
sizeof
(
VALUE
) *
RSTRUCT_LEN
(obj);
142
}
143
break
;
144
145
case
T_ZOMBIE
:
146
break
;
147
148
default
:
149
rb_bug
(
"objspace/memsize_of(): unknown data type 0x%x(%p)"
,
150
BUILTIN_TYPE
(obj), (
void
*)obj);
151
}
152
153
return
size
;
154
}
155
156
/*
157
* call-seq:
158
* ObjectSpace.memsize_of(obj) -> Integer
159
*
160
* Return consuming memory size of obj.
161
*
162
* Note that the return size is incomplete. You need to deal with
163
* this information as only a *HINT*. Especially, the size of
164
* T_DATA may not be correct.
165
*
166
* This method is not expected to work except C Ruby.
167
*/
168
169
static
VALUE
170
memsize_of_m
(
VALUE
self
,
VALUE
obj)
171
{
172
return
SIZET2NUM
(
memsize_of
(obj));
173
}
174
175
struct
total_data
{
176
size_t
total
;
177
VALUE
klass
;
178
};
179
180
static
int
181
total_i
(
void
*vstart,
void
*vend,
size_t
stride,
void
*ptr)
182
{
183
VALUE
v
;
184
struct
total_data
*data = (
struct
total_data
*)ptr;
185
186
for
(v = (
VALUE
)vstart; v != (
VALUE
)vend; v += stride) {
187
if
(
RBASIC
(v)->flags) {
188
switch
(
BUILTIN_TYPE
(v)) {
189
case
T_NONE
:
190
case
T_ICLASS
:
191
case
T_NODE
:
192
case
T_ZOMBIE
:
193
continue
;
194
case
T_CLASS
:
195
if
(
FL_TEST
(v,
FL_SINGLETON
))
196
continue
;
197
default
:
198
if
(data->
klass
== 0 ||
rb_obj_is_kind_of
(v, data->
klass
)) {
199
data->
total
+=
memsize_of
(v);
200
}
201
}
202
}
203
}
204
205
return
0;
206
}
207
208
/*
209
* call-seq:
210
* ObjectSpace.memsize_of_all([klass]) -> Integer
211
*
212
* Return consuming memory size of all living objects.
213
* If klass (should be Class object) is given, return the total
214
* memory size of instances of the given class.
215
*
216
* Note that the returned size is incomplete. You need to deal with
217
* this information as only a *HINT*. Especially, the size of
218
* T_DATA may not be correct.
219
*
220
* Note that this method does *NOT* return total malloc'ed memory size.
221
*
222
* This method can be defined by the following Ruby code:
223
*
224
* def memsize_of_all klass = false
225
* total = 0
226
* ObjectSpace.each_objects{|e|
227
* total += ObjectSpace.memsize_of(e) if klass == false || e.kind_of?(klass)
228
* }
229
* total
230
* end
231
*
232
* This method is not expected to work except C Ruby.
233
*/
234
235
static
VALUE
236
memsize_of_all_m
(
int
argc
,
VALUE
*
argv
,
VALUE
self
)
237
{
238
struct
total_data
data = {0, 0};
239
240
if
(argc > 0) {
241
rb_scan_args
(argc, argv,
"01"
, &data.
klass
);
242
}
243
244
rb_objspace_each_objects
(
total_i
, &data);
245
return
SIZET2NUM
(data.
total
);
246
}
247
248
static
int
249
set_zero_i
(
st_data_t
key
,
st_data_t
val,
st_data_t
arg
)
250
{
251
VALUE
k = (
VALUE
)key;
252
VALUE
hash
= (
VALUE
)arg;
253
rb_hash_aset
(hash, k,
INT2FIX
(0));
254
return
ST_CONTINUE
;
255
}
256
257
static
int
258
cos_i
(
void
*vstart,
void
*vend,
size_t
stride,
void
*data)
259
{
260
size_t
*counts = (
size_t
*)data;
261
VALUE
v
= (
VALUE
)vstart;
262
263
for
(;v != (
VALUE
)vend; v += stride) {
264
if
(
RBASIC
(v)->flags) {
265
counts[
BUILTIN_TYPE
(v)] +=
memsize_of
(v);
266
}
267
}
268
return
0;
269
}
270
271
/*
272
* call-seq:
273
* ObjectSpace.count_objects_size([result_hash]) -> hash
274
*
275
* Counts objects size (in bytes) for each type.
276
*
277
* Note that this information is incomplete. You need to deal with
278
* this information as only a *HINT*. Especially, total size of
279
* T_DATA may not right size.
280
*
281
* It returns a hash as:
282
* {:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...}
283
*
284
* If the optional argument, result_hash, is given,
285
* it is overwritten and returned.
286
* This is intended to avoid probe effect.
287
*
288
* The contents of the returned hash is implementation defined.
289
* It may be changed in future.
290
*
291
* This method is not expected to work except C Ruby.
292
*/
293
294
static
VALUE
295
count_objects_size
(
int
argc
,
VALUE
*
argv
,
VALUE
os)
296
{
297
size_t
counts[
T_MASK
+1];
298
size_t
total
= 0;
299
size_t
i
;
300
VALUE
hash
;
301
302
if
(
rb_scan_args
(argc, argv,
"01"
, &hash) == 1) {
303
if
(
TYPE
(hash) !=
T_HASH
)
304
rb_raise
(
rb_eTypeError
,
"non-hash given"
);
305
}
306
307
for
(i = 0; i <=
T_MASK
; i++) {
308
counts[
i
] = 0;
309
}
310
311
rb_objspace_each_objects
(
cos_i
, &counts[0]);
312
313
if
(hash ==
Qnil
) {
314
hash =
rb_hash_new
();
315
}
316
else
if
(!
RHASH_EMPTY_P
(hash)) {
317
st_foreach
(
RHASH_TBL
(hash),
set_zero_i
, hash);
318
}
319
320
for
(i = 0; i <=
T_MASK
; i++) {
321
if
(counts[i]) {
322
VALUE
type
;
323
switch
(i) {
324
#define COUNT_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
325
COUNT_TYPE
(
T_NONE
);
326
COUNT_TYPE
(
T_OBJECT
);
327
COUNT_TYPE
(
T_CLASS
);
328
COUNT_TYPE
(
T_MODULE
);
329
COUNT_TYPE
(
T_FLOAT
);
330
COUNT_TYPE
(
T_STRING
);
331
COUNT_TYPE
(
T_REGEXP
);
332
COUNT_TYPE
(
T_ARRAY
);
333
COUNT_TYPE
(
T_HASH
);
334
COUNT_TYPE
(
T_STRUCT
);
335
COUNT_TYPE
(
T_BIGNUM
);
336
COUNT_TYPE
(
T_FILE
);
337
COUNT_TYPE
(
T_DATA
);
338
COUNT_TYPE
(
T_MATCH
);
339
COUNT_TYPE
(
T_COMPLEX
);
340
COUNT_TYPE
(
T_RATIONAL
);
341
COUNT_TYPE
(
T_NIL
);
342
COUNT_TYPE
(
T_TRUE
);
343
COUNT_TYPE
(
T_FALSE
);
344
COUNT_TYPE
(
T_SYMBOL
);
345
COUNT_TYPE
(
T_FIXNUM
);
346
COUNT_TYPE
(
T_UNDEF
);
347
COUNT_TYPE
(
T_NODE
);
348
COUNT_TYPE
(
T_ICLASS
);
349
COUNT_TYPE
(
T_ZOMBIE
);
350
#undef COUNT_TYPE
351
default
: type =
INT2NUM
(i);
break
;
352
}
353
total += counts[
i
];
354
rb_hash_aset
(hash, type,
SIZET2NUM
(counts[i]));
355
}
356
}
357
rb_hash_aset
(hash,
ID2SYM
(
rb_intern
(
"TOTAL"
)),
SIZET2NUM
(total));
358
return
hash
;
359
}
360
361
static
int
362
cn_i
(
void
*vstart,
void
*vend,
size_t
stride,
void
*n)
363
{
364
size_t
*nodes = (
size_t
*)n;
365
VALUE
v
= (
VALUE
)vstart;
366
367
for
(; v != (
VALUE
)vend; v += stride) {
368
if
(
RBASIC
(v)->flags &&
BUILTIN_TYPE
(v) ==
T_NODE
) {
369
size_t
s =
nd_type
((
NODE
*)v);
370
nodes[s]++;
371
}
372
}
373
374
return
0;
375
}
376
377
/*
378
* call-seq:
379
* ObjectSpace.count_nodes([result_hash]) -> hash
380
*
381
* Counts nodes for each node type.
382
*
383
* This method is not for ordinary Ruby programmers, but for MRI developers
384
* who have interest in MRI performance and memory usage.
385
*
386
* It returns a hash as:
387
* {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
388
*
389
* If the optional argument, result_hash, is given,
390
* it is overwritten and returned.
391
* This is intended to avoid probe effect.
392
*
393
* The contents of the returned hash is implementation defined.
394
* It may be changed in future.
395
*
396
* This method is not expected to work except C Ruby.
397
*/
398
399
static
VALUE
400
count_nodes
(
int
argc
,
VALUE
*
argv
,
VALUE
os)
401
{
402
size_t
nodes[
NODE_LAST
+1];
403
size_t
i
;
404
VALUE
hash
;
405
406
if
(
rb_scan_args
(argc, argv,
"01"
, &hash) == 1) {
407
if
(
TYPE
(hash) !=
T_HASH
)
408
rb_raise
(
rb_eTypeError
,
"non-hash given"
);
409
}
410
411
for
(i = 0; i <=
NODE_LAST
; i++) {
412
nodes[
i
] = 0;
413
}
414
415
rb_objspace_each_objects
(
cn_i
, &nodes[0]);
416
417
if
(hash ==
Qnil
) {
418
hash =
rb_hash_new
();
419
}
420
else
if
(!
RHASH_EMPTY_P
(hash)) {
421
st_foreach
(
RHASH_TBL
(hash),
set_zero_i
, hash);
422
}
423
424
for
(i=0; i<
NODE_LAST
; i++) {
425
if
(nodes[i] != 0) {
426
VALUE
node;
427
switch
(i) {
428
#define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); break;
429
COUNT_NODE
(
NODE_SCOPE
);
430
COUNT_NODE
(
NODE_BLOCK
);
431
COUNT_NODE
(
NODE_IF
);
432
COUNT_NODE
(
NODE_CASE
);
433
COUNT_NODE
(
NODE_WHEN
);
434
COUNT_NODE
(
NODE_OPT_N
);
435
COUNT_NODE
(
NODE_WHILE
);
436
COUNT_NODE
(
NODE_UNTIL
);
437
COUNT_NODE
(
NODE_ITER
);
438
COUNT_NODE
(
NODE_FOR
);
439
COUNT_NODE
(
NODE_BREAK
);
440
COUNT_NODE
(
NODE_NEXT
);
441
COUNT_NODE
(
NODE_REDO
);
442
COUNT_NODE
(
NODE_RETRY
);
443
COUNT_NODE
(
NODE_BEGIN
);
444
COUNT_NODE
(
NODE_RESCUE
);
445
COUNT_NODE
(
NODE_RESBODY
);
446
COUNT_NODE
(
NODE_ENSURE
);
447
COUNT_NODE
(
NODE_AND
);
448
COUNT_NODE
(
NODE_OR
);
449
COUNT_NODE
(
NODE_MASGN
);
450
COUNT_NODE
(
NODE_LASGN
);
451
COUNT_NODE
(
NODE_DASGN
);
452
COUNT_NODE
(
NODE_DASGN_CURR
);
453
COUNT_NODE
(
NODE_GASGN
);
454
COUNT_NODE
(
NODE_IASGN
);
455
COUNT_NODE
(
NODE_IASGN2
);
456
COUNT_NODE
(
NODE_CDECL
);
457
COUNT_NODE
(
NODE_CVASGN
);
458
COUNT_NODE
(
NODE_CVDECL
);
459
COUNT_NODE
(
NODE_OP_ASGN1
);
460
COUNT_NODE
(
NODE_OP_ASGN2
);
461
COUNT_NODE
(
NODE_OP_ASGN_AND
);
462
COUNT_NODE
(
NODE_OP_ASGN_OR
);
463
COUNT_NODE
(
NODE_CALL
);
464
COUNT_NODE
(
NODE_FCALL
);
465
COUNT_NODE
(
NODE_VCALL
);
466
COUNT_NODE
(
NODE_SUPER
);
467
COUNT_NODE
(
NODE_ZSUPER
);
468
COUNT_NODE
(
NODE_ARRAY
);
469
COUNT_NODE
(
NODE_ZARRAY
);
470
COUNT_NODE
(
NODE_VALUES
);
471
COUNT_NODE
(
NODE_HASH
);
472
COUNT_NODE
(
NODE_RETURN
);
473
COUNT_NODE
(
NODE_YIELD
);
474
COUNT_NODE
(
NODE_LVAR
);
475
COUNT_NODE
(
NODE_DVAR
);
476
COUNT_NODE
(
NODE_GVAR
);
477
COUNT_NODE
(
NODE_IVAR
);
478
COUNT_NODE
(
NODE_CONST
);
479
COUNT_NODE
(
NODE_CVAR
);
480
COUNT_NODE
(
NODE_NTH_REF
);
481
COUNT_NODE
(
NODE_BACK_REF
);
482
COUNT_NODE
(
NODE_MATCH
);
483
COUNT_NODE
(
NODE_MATCH2
);
484
COUNT_NODE
(
NODE_MATCH3
);
485
COUNT_NODE
(
NODE_LIT
);
486
COUNT_NODE
(
NODE_STR
);
487
COUNT_NODE
(
NODE_DSTR
);
488
COUNT_NODE
(
NODE_XSTR
);
489
COUNT_NODE
(
NODE_DXSTR
);
490
COUNT_NODE
(
NODE_EVSTR
);
491
COUNT_NODE
(
NODE_DREGX
);
492
COUNT_NODE
(
NODE_DREGX_ONCE
);
493
COUNT_NODE
(
NODE_ARGS
);
494
COUNT_NODE
(
NODE_ARGS_AUX
);
495
COUNT_NODE
(
NODE_OPT_ARG
);
496
COUNT_NODE
(
NODE_POSTARG
);
497
COUNT_NODE
(
NODE_ARGSCAT
);
498
COUNT_NODE
(
NODE_ARGSPUSH
);
499
COUNT_NODE
(
NODE_SPLAT
);
500
COUNT_NODE
(
NODE_TO_ARY
);
501
COUNT_NODE
(
NODE_BLOCK_ARG
);
502
COUNT_NODE
(
NODE_BLOCK_PASS
);
503
COUNT_NODE
(
NODE_DEFN
);
504
COUNT_NODE
(
NODE_DEFS
);
505
COUNT_NODE
(
NODE_ALIAS
);
506
COUNT_NODE
(
NODE_VALIAS
);
507
COUNT_NODE
(
NODE_UNDEF
);
508
COUNT_NODE
(
NODE_CLASS
);
509
COUNT_NODE
(
NODE_MODULE
);
510
COUNT_NODE
(
NODE_SCLASS
);
511
COUNT_NODE
(
NODE_COLON2
);
512
COUNT_NODE
(
NODE_COLON3
);
513
COUNT_NODE
(
NODE_DOT2
);
514
COUNT_NODE
(
NODE_DOT3
);
515
COUNT_NODE
(
NODE_FLIP2
);
516
COUNT_NODE
(
NODE_FLIP3
);
517
COUNT_NODE
(
NODE_SELF
);
518
COUNT_NODE
(
NODE_NIL
);
519
COUNT_NODE
(
NODE_TRUE
);
520
COUNT_NODE
(
NODE_FALSE
);
521
COUNT_NODE
(
NODE_ERRINFO
);
522
COUNT_NODE
(
NODE_DEFINED
);
523
COUNT_NODE
(
NODE_POSTEXE
);
524
COUNT_NODE
(
NODE_ALLOCA
);
525
COUNT_NODE
(
NODE_BMETHOD
);
526
COUNT_NODE
(
NODE_MEMO
);
527
COUNT_NODE
(
NODE_IFUNC
);
528
COUNT_NODE
(
NODE_DSYM
);
529
COUNT_NODE
(
NODE_ATTRASGN
);
530
COUNT_NODE
(
NODE_PRELUDE
);
531
COUNT_NODE
(
NODE_LAMBDA
);
532
COUNT_NODE
(
NODE_OPTBLOCK
);
533
#undef COUNT_NODE
534
default
: node =
INT2FIX
(i);
535
}
536
rb_hash_aset
(hash, node,
SIZET2NUM
(nodes[i]));
537
}
538
}
539
return
hash
;
540
}
541
542
static
int
543
cto_i
(
void
*vstart,
void
*vend,
size_t
stride,
void
*data)
544
{
545
VALUE
hash
= (
VALUE
)data;
546
VALUE
v
= (
VALUE
)vstart;
547
548
for
(; v != (
VALUE
)vend; v += stride) {
549
if
(
RBASIC
(v)->flags &&
BUILTIN_TYPE
(v) ==
T_DATA
) {
550
VALUE
counter;
551
VALUE
key
=
RBASIC
(v)->klass;
552
553
if
(key == 0) {
554
const
char
*
name
=
rb_objspace_data_type_name
(v);
555
if
(name == 0) name =
"unknown"
;
556
key =
ID2SYM
(
rb_intern
(name));
557
}
558
559
counter =
rb_hash_aref
(hash, key);
560
if
(
NIL_P
(counter)) {
561
counter =
INT2FIX
(1);
562
}
563
else
{
564
counter =
INT2FIX
(
FIX2INT
(counter) + 1);
565
}
566
567
rb_hash_aset
(hash, key, counter);
568
}
569
}
570
571
return
0;
572
}
573
574
/*
575
* call-seq:
576
* ObjectSpace.count_tdata_objects([result_hash]) -> hash
577
*
578
* Counts objects for each T_DATA type.
579
*
580
* This method is not for ordinary Ruby programmers, but for MRI developers
581
* who interest on MRI performance.
582
*
583
* It returns a hash as:
584
* {RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6,
585
* :mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99,
586
* ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1,
587
* Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2}
588
* # T_DATA objects existing at startup on r32276.
589
*
590
* If the optional argument, result_hash, is given,
591
* it is overwritten and returned.
592
* This is intended to avoid probe effect.
593
*
594
* The contents of the returned hash is implementation defined.
595
* It may be changed in future.
596
*
597
* In this version, keys are Class object or Symbol object.
598
* If object is kind of normal (accessible) object, the key is Class object.
599
* If object is not a kind of normal (internal) object, the key is symbol
600
* name, registered by rb_data_type_struct.
601
*
602
* This method is not expected to work except C Ruby.
603
*
604
*/
605
606
static
VALUE
607
count_tdata_objects
(
int
argc
,
VALUE
*
argv
,
VALUE
self
)
608
{
609
VALUE
hash
;
610
611
if
(
rb_scan_args
(argc, argv,
"01"
, &hash) == 1) {
612
if
(
TYPE
(hash) !=
T_HASH
)
613
rb_raise
(
rb_eTypeError
,
"non-hash given"
);
614
}
615
616
if
(hash ==
Qnil
) {
617
hash =
rb_hash_new
();
618
}
619
else
if
(!
RHASH_EMPTY_P
(hash)) {
620
st_foreach
(
RHASH_TBL
(hash),
set_zero_i
, hash);
621
}
622
623
rb_objspace_each_objects
(
cto_i
, (
void
*)hash);
624
625
return
hash
;
626
}
627
628
/* objspace library extends ObjectSpace module and add several
629
* methods to get internal statistic information about
630
* object/memory management.
631
*
632
* Generally, you *SHOULD NOT*use this library if you do not know
633
* about the MRI implementation. Mainly, this library is for (memory)
634
* profiler developers and MRI developers who need to know how MRI
635
* memory usage.
636
*/
637
638
void
639
Init_objspace
(
void
)
640
{
641
VALUE
rb_mObjSpace =
rb_const_get
(
rb_cObject
,
rb_intern
(
"ObjectSpace"
));
642
643
rb_define_module_function
(rb_mObjSpace,
"memsize_of"
,
memsize_of_m
, 1);
644
rb_define_module_function
(rb_mObjSpace,
"memsize_of_all"
,
645
memsize_of_all_m
, -1);
646
647
rb_define_module_function
(rb_mObjSpace,
"count_objects_size"
,
count_objects_size
, -1);
648
rb_define_module_function
(rb_mObjSpace,
"count_nodes"
,
count_nodes
, -1);
649
rb_define_module_function
(rb_mObjSpace,
"count_tdata_objects"
,
count_tdata_objects
, -1);
650
}
651
Generated on Fri Jun 28 2013 02:34:34 for Ruby by
1.8.3