对我来说,纤维是一个相对较新的概念。我知道每根光纤的堆栈大小限制为4kB,我一直在读,我应该“提防”这一点。此限制在现实世界中会产生什么后果?
编辑:
看来,毕竟4kB的限制并不是什么障碍,并且光纤本身需要大量局部变量(4,045)才能引发SystemStackError。
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次迭代中失败,并指示被调用方法中的变量成为光纤堆栈的一部分:
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的堆栈限制,尽管超过第3,500次迭代后,它变得越来越明显,并且变得越来越慢,而在第5,000次迭代中,它的平均速度约为每秒一次迭代。我不知道RBX是否有限制,因为我刚刚执行了5100多次迭代就退出了执行。 RBX所使用的内存也比MRI 1.9.3高出几倍。
JRuby 1.7似乎也没有4kB的光纤堆栈大小,如果光纤具有最大堆栈大小,那对我来说是未知的。我完成了第一个代码示例的5,000次迭代,没有出现问题,尽管可以预料,JVM占用了数百MB的RAM。
最佳答案
这样做的后果是您必须更加注意光纤代码的内存,因为您可能会发生内存泄漏。
一些递归函数可能会给您带来问题