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

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 

这取决于Ruby的实现。

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

请参阅“MRI内存分配 – 开发人员入门”和“揭开Ruby GC的神秘面纱”

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

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

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

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

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

纤维

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

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

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

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

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