首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ruby的4kB光纤堆栈大小的后果

Ruby的4kB光纤堆栈大小的后果
EN

Stack Overflow用户
提问于 2012-11-30 11:18:58
回答 2查看 1.2K关注 0票数 12

纤维对我来说是一个相对较新的概念。我知道每根光纤的堆叠大小被限制在4kB,我一直在读,我应该“小心”这一点。这种限制在现实世界中的后果到底是什么?

编辑:

看起来这个4kB的限制并不是一个很大的障碍,它需要在纤程内部使用大量的局部变量(4,045)才能引发SystemStackError。

代码语言:javascript
复制
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

这不是最优雅的代码,但它似乎确实演示了光纤堆栈的局限性。似乎只有返回值、局部变量(所有这些变量都包含对堆上对象的引用)和方法调用被放入堆栈。我还没有测试从纤程调用的方法中的局部变量等是否属于纤程堆栈的一部分。

编辑2:

修改了上述代码。似乎被调用方法中的变量等确实成为了纤程堆栈的一部分。如果是这种情况,那么调用深度(即使没有递归)可能是更大的问题,因为方法本身可能比变量(似乎是对堆上对象的透明引用)需要更多的堆栈空间。

下面的代码在第4,031次迭代中失败,并指示被调用方法中的变量成为纤程堆栈的一部分:

代码语言:javascript
复制
count = 0
loop do
  count += 1
  puts count
  varlist = String.new
  count.times do |i|
    varlist += "a#{i} = 1\n"
  end
  m = "def meth\n #{varlist} \n end"
  eval(m)
  fiber = Fiber.new do
    meth
  end
  fiber.resume
end

编辑3:

我刚刚尝试在Rubinius 2.0上运行初始代码示例。它的光纤似乎没有4kB的堆栈限制,尽管超过大约3500次迭代后,它变得越来越慢,并且在大约5000次迭代时,它平均每秒大约有一次迭代。我不知道RBX是否有限制,因为我在超过5,100次迭代时退出执行。RBX使用的内存也是MRI 1.9.3的几倍。

JRuby 1.7似乎也没有4kB的光纤堆栈大小,如果光纤有最大堆栈大小,我是不知道的。我完成了第一个代码示例的5000次迭代,没有出现问题,尽管如预期的那样,JVM消耗了几百MB的RAM。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-11-30 11:29:28

这样做的后果是,您必须更加关注您的纤程代码的内存,因为您可能会有内存泄漏。

一些递归函数可能会给您带来问题

票数 2
EN

Stack Overflow用户

发布于 2012-11-30 11:57:02

正如Anton在他的回答中所提到的,您可以在纤程中使用内存密集型代码。可能(潜在地)消耗大量内存的东西的例子:

  • 大字符串(即:包含相当大的HTTP response)
  • Recursive函数(堆栈级别太深!)的字符串)
  • 流或类似流的对象:要非常小心流缓冲区;如果它们接近或超过4k,您将开始看到一些非常奇怪的行为
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13638503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档