在Ruby中,存储在堆栈中的是什么?

Mat*_*tty 23 ruby memory variables heap stack

Ruby是否在堆上分配所有内容,或者是否有任何存储在堆栈中的实例?我的印象是所有变量基本上都在堆栈上,并且包含对堆上对象的透明引用.我这个想法是否正确?这个实现是否具体?

另外,如果是在堆栈上分配变量并且仅包含隐藏指针的情况,那么变量本身(忽略它们指向的对象)消耗了多少字节?

编辑:

问这个问题是因为我试图弄清楚光纤的4kB堆栈限制是否会成为这个问题的一个问题.似乎(使用MRI 1.9.3)每个变量本身消耗一个字节,并且与光纤相关的开销很小,这使得可用的堆栈大小减少了几个字节.

此代码将在第4,045次迭代时失败:

count = 0
loop do
  count += 1
  puts count
  varlist = String.new
  count.times do |i|
    varlist += "a#{i} = 1\n"
  end
  s = "fiber = Fiber.new do \n #{varlist} \n end \n fiber.resume"
  eval(s)
end
Run Code Online (Sandbox Code Playgroud)

joe*_*son 21

这取决于Ruby的实现.

例如,Ruby 2.0 MRI(大多数系统中的典型)将所有对象存储在堆中.诸如短弦之类的小物体可以完全装入堆中.对于大型对象,Ruby将在堆外部使用malloc额外的内存.

请参阅"MRI内存分配 - 面向开发人员的入门""揭开Ruby GC的神秘面纱"

这是"理解Ruby如何在内存中存储对象",它具有更好,更长的描述:

"对象在内存中占用的整个空间不存储在Slot中.而是每个Slot都是一个小的固定大小的空间,可以被认为是Ruby解释器处理内存中的一个位置.这个位置存在于Ruby堆之外它本身并包含对象的真正"肉".要清楚,如果你有一个50MB的字符串 - 50MB的数据存储在Ruby的堆之外.如果你真的想知道50MB的故事,它的空间实际上是通过C语言中的malloc命令分配的(好的ol'Ruby是用C编写的),然后存储在系统堆中.Ruby堆中的Slot只包含对System Heap中包含的内存位置的引用50MB的数据."

"Ruby拥有自己的堆管理,它实际上包含几个'Ruby Heaps'来管理在Ruby程序执行期间创建的对象;这与操作系统的系统堆是分开的.每个Ruby Heap都包含Slots,每个Slot能够引用一个对象.

另一个很好的资源是" Ruby如何管理内存和垃圾收集 ",它链接到" LA Ruby Conference的垃圾收集幻灯片 "中的幻灯片.

"作为一种垃圾收集语言,Ruby通过将所有内容放在堆上来实现简单的路径".

纤维

纤维在Ruby中是特殊的,因为每根纤维都有自己的小堆栈.

"与其他无堆栈轻量级并发模型相比,每个光纤都带有一个4KB的小堆栈.这使得光纤可以通过光纤模块内的深度嵌套函数调用暂停."

您可能对动态光纤堆栈大小的长期运行功能请求感兴趣.

如果您对实际解决方案更感兴趣,那么功能请求作者建议使用此解决方法:"重构需要大型堆栈在单独线程中运行然后在thread.value上阻塞的操作."

您还可以考虑使用您自己的cont.c源文件中的FIBER_MACHINE_STACK_ALLOCATION_SIZE和FIBER_VM_STACK_SIZE选择编译自定义版本的Ruby .该文件还显示了如何分配,释放光纤堆栈等.