Волокна для меня - относительно новое понятие. Я знаю, что размер стека каждого волокна ограничен 4 КБ, и я продолжаю читать, что мне следует «остерегаться» этого. Каковы именно последствия этого ограничения в реальном мире?
Редактировать:
Кажется, что это ограничение в 4 КБ в конце концов не является таким препятствием, и требуется большое количество локальных переменных (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:
Изменил приведенный выше код. Кажется, что переменные и т. Д. В вызываемых методах становятся частью стека волокна. Если это так, то глубина вызова (даже без рекурсии) может быть более серьезной проблемой, поскольку сами методы, вероятно, потребуют больше места в стеке, чем переменные (которые кажутся прозрачными ссылками на объекты в куче).
Следующий код не работает на 4031-й итерации и указывает, что переменные в вызываемых методах становятся частью стека волокна:
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, потому что я прекращаю выполнение чуть более чем через 5100 итераций. RBX также использует в несколько раз больше памяти, чем MRI 1.9.3.
JRuby 1.7 также, похоже, не имеет размера стека 4 КБ для волокон, и если волокна имеют максимальный размер стека, мне это неизвестно. Я без проблем выполнил 5000 итераций первого примера кода, хотя, как и следовало ожидать, JVM потратила несколько сотен МБ ОЗУ.