纤维对我来说是一个相对较新的概念。我知道每根光纤的堆叠大小被限制在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的堆栈限制,尽管超过大约3500次迭代后,它变得越来越慢,并且在大约5000次迭代时,它平均每秒大约有一次迭代。我不知道RBX是否有限制,因为我在超过5,100次迭代时退出执行。RBX使用的内存也是MRI 1.9.3的几倍。
JRuby 1.7似乎也没有4kB的光纤堆栈大小,如果光纤有最大堆栈大小,我是不知道的。我完成了第一个代码示例的5000次迭代,没有出现问题,尽管如预期的那样,JVM消耗了几百MB的RAM。
发布于 2012-11-30 11:29:28
这样做的后果是,您必须更加关注您的纤程代码的内存,因为您可能会有内存泄漏。
一些递归函数可能会给您带来问题
发布于 2012-11-30 11:57:02
正如Anton在他的回答中所提到的,您可以在纤程中使用内存密集型代码。可能(潜在地)消耗大量内存的东西的例子:
https://stackoverflow.com/questions/13638503
复制相似问题