这是复制问题的示例代码。
# test.rb
n = 100000
res = {}
1.upto(n).to_a.inject(res) do |r, i|
r[i] = {}
end
def f(x)
x.each_value { |v| f(v) }
end
f(res)
使用Docker Hub提供的Docker图像运行此代码。
- Alpine Linux中的Ruby 2.5.0是意外(不太深)
- Alpine Linux中的Ruby 2.4.3是预期
- ruby 2.5.0在debian是预期
是什么有所作为?
补充说明
(对不起,我的英语不好。)
这是一个补充解释。
我知道示例代码原因SystemStackError。我编写了示例代码来导致SystemStackError。
我想知道"级别"差异的原因。
- Alpine Linux中的Ruby 2.5.0->" ... 137级..."
- Alpine Linux中的Ruby 2.4.3 ->" ... 10067级..."
- ruby 2.5.0在debian->" ... 9866级别..."
Ruby 2.5.0 Alpine Linux(Ruby:2.5.0-Alpine3.7)
在这种情况下,堆栈级别为137。
% docker container run -v (pwd):/mnt/my --rm -it ruby:2.5.0-alpine3.7 ruby -v /mnt/my/test.rb
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux-musl]
Traceback (most recent call last):
149: from /mnt/my/test.rb:11:in `<main>'
148: from /mnt/my/test.rb:8:in `f'
147: from /mnt/my/test.rb:8:in `each_value'
146: from /mnt/my/test.rb:8:in `block in f'
145: from /mnt/my/test.rb:8:in `f'
144: from /mnt/my/test.rb:8:in `each_value'
143: from /mnt/my/test.rb:8:in `block in f'
142: from /mnt/my/test.rb:8:in `f'
... 137 levels...
4: from /mnt/my/test.rb:8:in `f'
3: from /mnt/my/test.rb:8:in `each_value'
2: from /mnt/my/test.rb:8:in `block in f'
1: from /mnt/my/test.rb:8:in `f'
/mnt/my/test.rb:8:in `each_value': stack level too deep (SystemStackError)
但简单的情况,堆栈级别为13092。
% docker container run --rm -it ruby:2.5.0-alpine3.7 ruby -v -e 'def f; f; end; f'
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux-musl]
Traceback (most recent call last):
13104: from -e:1:in `<main>'
13103: from -e:1:in `f'
13102: from -e:1:in `f'
13101: from -e:1:in `f'
13100: from -e:1:in `f'
13099: from -e:1:in `f'
13098: from -e:1:in `f'
13097: from -e:1:in `f'
... 13092 levels...
4: from -e:1:in `f'
3: from -e:1:in `f'
2: from -e:1:in `f'
1: from -e:1:in `f'
-e:1:in `f': stack level too deep (SystemStackError)
Ruby 2.4.3 Alpine Linux(Ruby:2.4.3-Alpine3.7)
在这种情况下,堆栈级别为10067。与上述情况有很大的区别。
% docker container run -v (pwd):/mnt/my --rm -it ruby:2.4.3-alpine3.7 ruby -v /mnt/my/test.rb
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-linux-musl]
/mnt/my/test.rb:8:in `each_value': stack level too deep (SystemStackError)
from /mnt/my/test.rb:8:in `f'
from /mnt/my/test.rb:8:in `block in f'
from /mnt/my/test.rb:8:in `each_value'
from /mnt/my/test.rb:8:in `f'
from /mnt/my/test.rb:8:in `block in f'
from /mnt/my/test.rb:8:in `each_value'
from /mnt/my/test.rb:8:in `f'
from /mnt/my/test.rb:8:in `block in f'
... 10067 levels...
from /mnt/my/test.rb:8:in `block in f'
from /mnt/my/test.rb:8:in `each_value'
from /mnt/my/test.rb:8:in `f'
from /mnt/my/test.rb:11:in `<main>'
i显示 diff dockerfile的输出。
--- 2.4/alpine3.7/Dockerfile 2017-12-28 20:34:43.000000000 +0900
+++ 2.5/alpine3.7/Dockerfile 2017-12-28 20:34:43.000000000 +0900
@@ -7,9 +7,9 @@
echo 'update: --no-document';
} >> /usr/local/etc/gemrc
-ENV RUBY_MAJOR 2.4
-ENV RUBY_VERSION 2.4.3
-ENV RUBY_DOWNLOAD_SHA256 23677d40bf3b7621ba64593c978df40b1e026d8653c74a0599f0ead78ed92b51
+ENV RUBY_MAJOR 2.5
+ENV RUBY_VERSION 2.5.0
+ENV RUBY_DOWNLOAD_SHA256 1da0afed833a0dab94075221a615c14487b05d0c407f991c8080d576d985b49b
ENV RUBYGEMS_VERSION 2.7.4
ENV BUNDLER_VERSION 1.16.1
这意味着使用相同的高山Linux。只是红宝石是不同的。
Ruby 2.5.0 Debian(Ruby:2.5.0-stretch)
在这种情况下,堆栈级别为9866。这种情况使用Ruby 2.5.0,但在Debian(不是Alpine)运行。
% docker container run -v (pwd):/mnt/my --rm -it ruby:2.5.0-stretch ruby -v /mnt/my/test.rb
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
Traceback (most recent call last):
9878: from /mnt/my/test.rb:11:in `<main>'
9877: from /mnt/my/test.rb:8:in `f'
9876: from /mnt/my/test.rb:8:in `each_value'
9875: from /mnt/my/test.rb:8:in `block in f'
9874: from /mnt/my/test.rb:8:in `f'
9873: from /mnt/my/test.rb:8:in `each_value'
9872: from /mnt/my/test.rb:8:in `block in f'
9871: from /mnt/my/test.rb:8:in `f'
... 9866 levels...
4: from /mnt/my/test.rb:8:in `f'
3: from /mnt/my/test.rb:8:in `each_value'
2: from /mnt/my/test.rb:8:in `block in f'
1: from /mnt/my/test.rb:8:in `f'
/mnt/my/test.rb:8:in `each_value': stack level too deep (SystemStackError)
我们在某些边缘情况下也看到了这一点。我们已经确认在所有情况下,OS和Ruby堆栈尺寸都是相同的。(Alpine 2.4.3,Alpine 2.5.0,并在MacOS上本地运行2.5.0)
我们唯一能找到的差异化因素是Alpine 2.5.0图像是用Alpine 3.7构建的,Alpine 3.7用Libressl构建Ruby。2.4.3图像是由Alpine 3.4构建的,该图像仍在使用OpenSSL。我们的本地2.5.0反对OpenSSL构建,并未显示此"短"堆栈长度。