Волокна - относительно новая концепция для меня. Я знаю, что каждый размер стека волокон ограничен 4 КБ, и я продолжаю читать, что я должен "остерегаться" этого. Каковы реальные последствия этого предела для реального мира?
Edit:
Похоже, что это ограничение 4kB не является таким препятствием в конце концов и требует большого количества локальных переменных (4045) внутри самого волокна, чтобы вызвать повышение 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. На его волокнах нет предела стека 4 кБ, хотя после 3500-й итерации он становится все более и менее медленным, а около 5000-й итерации он усредняет примерно одну итерацию в секунду. Я не знаю, есть ли ограничение с RBX, потому что я выхожу из исполнения только с более чем 5 100 итерациями. RBX также использует в несколько раз больше памяти, чем MRI 1.9.3.
JRuby 1.7 также не имеет размера стека 4 кБ для волокон, и если волокна имеют максимальный размер стека, он мне неизвестен. Я завершил 5000 итераций первого примера кода без проблем, хотя, как и следовало ожидать, JVM пережевывала несколько сотен МБ ОЗУ.