【问题标题】:What are the meanings of the hash keys when calling ObjectSpace.count_objects?调用 ObjectSpace.count_objects 时哈希键的含义是什么?
【发布时间】:2026-02-03 22:15:02
【问题描述】:

在 Ruby 1.9 (YARV) 中,您可以获得所有当前分配的对象的计数,如下所示:

ObjectSpace.count_objects

返回一个类似的哈希

{:TOTAL=>1226560, :FREE=>244204, :T_OBJECT=>26141, :T_CLASS=>9819, :T_MODULE=>1420, :T_FLOAT=>287,
 :T_STRING=>260476, :T_REGEXP=>4081, :T_ARRAY=>72269, :T_HASH=>14923, :T_STRUCT=>4601, :T_BIGNUM=>7,
 :T_FILE=>16, :T_DATA=>54553, :T_MATCH=>5, :T_COMPLEX=>1, :T_RATIONAL=>15, :T_NODE=>524818, 
 :T_ICLASS=>8924}

这些哈希键的含义是什么?有些像 T_STRING 和 T_FILE 是显而易见的。我对 :FREE、:T_ICLASS、:T_DATA 和 :T_NODE 特别好奇。

【问题讨论】:

    标签: ruby


    【解决方案1】:

    只是一个猜测:我假设 :T_ICLASS 计数 包含类:T_NODE 可能代表 AST 节点

    这是一个完整的列表(遗憾的是没有 cmets):

    #define T_NONE   RUBY_T_NONE
    #define T_NIL    RUBY_T_NIL
    #define T_OBJECT RUBY_T_OBJECT
    #define T_CLASS  RUBY_T_CLASS
    #define T_ICLASS RUBY_T_ICLASS
    #define T_MODULE RUBY_T_MODULE
    #define T_FLOAT  RUBY_T_FLOAT
    #define T_STRING RUBY_T_STRING
    #define T_REGEXP RUBY_T_REGEXP
    #define T_ARRAY  RUBY_T_ARRAY
    #define T_HASH   RUBY_T_HASH
    #define T_STRUCT RUBY_T_STRUCT
    #define T_BIGNUM RUBY_T_BIGNUM
    #define T_FILE   RUBY_T_FILE
    #define T_FIXNUM RUBY_T_FIXNUM
    #define T_TRUE   RUBY_T_TRUE
    #define T_FALSE  RUBY_T_FALSE
    #define T_DATA   RUBY_T_DATA
    #define T_MATCH  RUBY_T_MATCH
    #define T_SYMBOL RUBY_T_SYMBOL
    #define T_RATIONAL RUBY_T_RATIONAL
    #define T_COMPLEX RUBY_T_COMPLEX
    #define T_UNDEF  RUBY_T_UNDEF
    #define T_NODE   RUBY_T_NODE
    #define T_ZOMBIE RUBY_T_ZOMBIE
    #define T_MASK   RUBY_T_MASK
    

    RUBY_T_xyz 枚举定义如下:

    enum ruby_value_type {
        RUBY_T_NONE   = 0x00,
    
        RUBY_T_OBJECT = 0x01,
        RUBY_T_CLASS  = 0x02,
        RUBY_T_MODULE = 0x03,
        RUBY_T_FLOAT  = 0x04,
        RUBY_T_STRING = 0x05,
        RUBY_T_REGEXP = 0x06,
        RUBY_T_ARRAY  = 0x07,
        RUBY_T_HASH   = 0x08,
        RUBY_T_STRUCT = 0x09,
        RUBY_T_BIGNUM = 0x0a,
        RUBY_T_FILE   = 0x0b,
        RUBY_T_DATA   = 0x0c,
        RUBY_T_MATCH  = 0x0d,
        RUBY_T_COMPLEX  = 0x0e,
        RUBY_T_RATIONAL = 0x0f,
    
        RUBY_T_NIL    = 0x11,
        RUBY_T_TRUE   = 0x12,
        RUBY_T_FALSE  = 0x13,
        RUBY_T_SYMBOL = 0x14,
        RUBY_T_FIXNUM = 0x15,
    
        RUBY_T_UNDEF  = 0x1b,
        RUBY_T_NODE   = 0x1c,
        RUBY_T_ICLASS = 0x1d,
        RUBY_T_ZOMBIE = 0x1e,
    
        RUBY_T_MASK   = 0x1f
    };
    

    我认为其中大部分都相当明显。我唯一想不通的是T_DATA(参见@banister 的评论)、T_ZOMBIET_MASK

    顺便说一句:请注意,这些 不是 Ruby 1.9 的一部分。它们是 YARV 的一部分。它们在 Ruby 1.9 的其他实现上可能完全不同,甚至根本不存在。文档明确指出:

    返回哈希的内容是实现定义的。将来可能会更改。

    事实上,甚至不能保证方法本身存在:

    除了 C Ruby 之外,该方法预计不会起作用。

    (作者据此推测该方法只保证在 MRI 和 YARV 上有效。)

    【讨论】:

    • :T_DATA 是一个数据包装结构
    【解决方案2】:

    您可以致电ObjectSpace.count_tdata_objects(描述为here)获取有关T_DATA 类别的更多信息。

    我相信这些是由 VM 控制的本机对象。有时原生扩展也可以分配它们。

    【讨论】:

      【解决方案3】:

      类型在 Ruby 源代码中的文件doc/extension.doc 中描述:

      T_NIL       :: nil
      T_OBJECT    :: ordinary object
      T_CLASS     :: class
      T_MODULE    :: module
      T_FLOAT     :: floating point number
      T_STRING    :: string
      T_REGEXP    :: regular expression
      T_ARRAY     :: array
      T_HASH      :: associative array
      T_STRUCT    :: (Ruby) structure
      T_BIGNUM    :: multi precision integer
      T_FIXNUM    :: Fixnum(31bit or 63bit integer)
      T_COMPLEX   :: complex number
      T_RATIONAL  :: rational number
      T_FILE      :: IO
      T_TRUE      :: true
      T_FALSE     :: false
      T_DATA      :: data
      T_SYMBOL    :: symbol
      

      此外,内部还使用了其他几种类型:

      T_ICLASS    :: included module
      T_MATCH     :: MatchData object
      T_UNDEF     :: undefined
      T_NODE      :: syntax tree node
      T_ZOMBIE    :: object awaiting finalization
      

      【讨论】: