【问题标题】:Size of class in bytes类的大小(以字节为单位)
【发布时间】:2013-05-03 14:50:24
【问题描述】:

有没有办法在 ruby​​ 中查看某个类的分配内存大小?

我已经建立了一个自定义类,我想知道它在内存中的大小。那么C语言中有没有类似sizeof()的函数呢?

我只是想像这样初始化一个新类

test = MyClass.new

并试图找到一种方法来打印出已分配到内存的类的大小。

这在 ruby​​ 中是否可行?

【问题讨论】:

  • 这个问题至少有两个复杂性:1)一个对象的所有属性也是其他类的对象,所以你需要清楚是否包含这些。 2)实例变量的数量和类型在Ruby中是动态的,所以并没有真正意义上的类的内存大小。但是,理论上您可以测量当前分配给对象的内存(尽管我目前不知道如何,或者 Ruby 是否允许您这样做)。

标签: ruby class memory methods


【解决方案1】:

没有任何语言功能可以像 C 一样计算类的大小。

对象的内存大小取决于实现。这取决于基类对象的实现。估计使用的内存也不简单。例如,如果字符串很短,则可以将它们嵌入到 RString 结构中,但如果它们很长,则存储在堆中 (Never create Ruby strings longer than 23 characters)。

某些对象占用的内存已针对不同的 ruby​​ 实现进行了列表:Memory footprint of objects in Ruby 1.8, EE, 1.9, and OCaml

最后,即使是来自同一个类的两个对象,对象大小也可能不同,因为可以任意添加额外的实例变量,而无需硬编码存在哪些实例变量。例如,请参阅instance_variable_getinstance_variable_set


如果您使用 MRI ruby​​ 1.9.2+,您可以尝试一种方法(请注意,它只查看对象的一部分,从整数和字符串的大小似乎为零这一事实可以看出这一点) :

irb(main):176:0> require 'objspace'
=> true
irb(main):176:0> ObjectSpace.memsize_of(134)
=> 0
irb(main):177:0> ObjectSpace.memsize_of("asdf")
=> 0
irb(main):178:0> ObjectSpace.memsize_of({a: 4})
=> 184
irb(main):179:0> ObjectSpace.memsize_of({a: 4, b: 5})
=> 232
irb(main):180:0> ObjectSpace.memsize_of(/a/.match("a"))
=> 80

你也可以试试 memsize_of_all (注意它看的是整个解释器的内存使用情况,覆盖一个变量似乎不会立即删除旧副本):

irb(main):190:0> ObjectSpace.memsize_of_all
=> 4190347
irb(main):191:0> asdf = 4
=> 4
irb(main):192:0> ObjectSpace.memsize_of_all
=> 4201350
irb(main):193:0> asdf = 4
=> 4
irb(main):194:0> ObjectSpace.memsize_of_all
=> 4212353
irb(main):195:0> asdf = 4.5
=> 4.5
irb(main):196:0> ObjectSpace.memsize_of_all
=> 4223596
irb(main):197:0> asdf = "a"
=> "a"
irb(main):198:0> ObjectSpace.memsize_of_all
=> 4234879

您应该非常小心,因为无法保证 Ruby 解释器何时会执行垃圾回收。虽然您可以将它用于测试和实验,但建议不要在生产中使用它!

【讨论】:

  • 那么这个怎么样。是否可以初始化 X 个类,然后在前后拉取 ruby​​ 解释器的内存使用量?我遇到了一个问题,他们自己的线程中的每个套接字都将获得我的 3 个类的一个副本(用于数据包处理等),所以如果有 10 个连接,那么我的每个类都有 30 个实例。我想知道这是否是一个基本的设计问题,我将不得不重新编码/考虑我的数据包处理,或者 3 个类是否会导致内存使用量很小。
  • 这产生了有趣的结果,当我简单地运行 puts ObjectSpace.memsize_of_all 时,我得到一个估计为 1180174 的值,但是当我运行 (0..1000).each do |i|; t.push PacketParser.new i; endputs ObjectSpace.memsize_of_all 时,我得到 920578 小于没有初始化我的 3000 多个课程是什么。除了垃圾处理之外,我还缺少什么吗?它实际上不是创建 3000 个类,而是简单地引用 3 个类或其他什么?
  • 我很难回答——你可以检查每一次迭代(也许你会在某些迭代中看到突然减少)。您应该知道,您不仅在上面的迭代中为对象分配内存。 PacketParser 构造函数和 t.push 方法也可以分配局部变量,这(临时)增加内存使用量。
  • 好吧,我进行了一些理论测试,得出了一个令人满意的结论,我可以接受。感谢所有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 2014-01-27
  • 2018-01-01
  • 2016-03-19
  • 1970-01-01
  • 1970-01-01
  • 2013-04-26
相关资源
最近更新 更多