我目前正在开发一个 ruby 应用程序,但它运行得非常(非常!)慢.. 到目前为止,我已经尝试了几件事,我可以将其缩小到主要问题:Ruby 正在尝试在 $LOAD_PATH 的每个目录中查找它的需求。
基本上我所观察到的是,ruby 正在查看大量 文件,试图查看那里是否存在需求。如果找不到它们,它将转到下一个目录。好消息是我可以通过 strace 看到这种情况。有很多这样的输出:
open("/boa_proj_build/nsteen/.gem/gems/i18n-0.7.0/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/thread_safe-0.3.5/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/tzinfo-1.2.2/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/minitest-5.8.2/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/activesupport-4.2.4/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/climate_control-0.0.3/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/cocaine-0.5.7/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/boa_loggable-0.2.2/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/ruby_expect-1.6.0/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/cctools-3.0.1/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/git-1.2.9.1/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/naught-1.1.0/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/symbolizer-0.0.1/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/settingslogic-2.0.9/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/memoist-0.12.0/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/highline-1.7.8/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/boa_proj_build/nsteen/.gem/gems/commander-4.3.5/lib/commander/help_formatters/base.rb", O_RDONLY|O_CLOEXEC) = 8
如您所见,它正在查看一些目录以找到它的要求。
使用测试应用程序对此进行跟踪,过滤 ENOENT 错误并对发生次数进行计数,显示以下有关输出:
vdi9442:/boa_proj_build/nsteen/$ strace packager --version 2>&1 | grep ENOENT | wc -l
3454261
当然,350 万是很多。这将导致大约 5 分钟的加载时间(如果没有 strace,大约一半),然后它会输出它的版本号(commander gem 的默认功能)。
我已经删除了我的整个 gem 主目录,然后再次运行测试,它立即变得更快,但我可以看到它再次查看了那几个 gem(依赖项,如 commander),但“只是”出现了几千次而不是 350 万。
我的 gem 环境看起来是这样的:
- GEM PATHS:
- /boa_proj_build/nsteen/.gem
- /home/nsteen/.gem/ruby/2.1.0
- /cadappl/ruby/2.1.1/ruby/lib/ruby/gems/2.1.0
看起来 ruby 只是遍历了我的整个加载路径,以满足一些依赖性。很好,但这只是变得荒谬。 有人知道发生了什么事吗?我怀疑这不是通缉/默认行为?
有人知道发生了什么事吗?我怎样才能加快速度?
最佳答案
有很多方法可以处理这个问题,包括我不会涉及的 gemrc 文件。我将提及您的一些选择:
解决方案一:
另一个答案是正确的,但我想就这个话题展开一点,因为人们似乎经常面对这个话题。 RVM 可以提供帮助。一个特殊的功能是为此而设计的, gem 集。我个人已经搬到 rbenv 并且没有回头。与 RVM 相比,Rbenv 对您的环境的干扰要小得多,但它们都很棒。您可以在 RVM 和 rbenv 中使用 gemset 来限制您的应用程序可用的 gem。您也可以制作特定于应用程序的 gemset。使用 gemset,您的应用程序将在一个位置查找,并且只会加载它使用过的 gem。它不会与其他应用程序 gemsets 混合。它最好的地方是自动的,你只需要设置一次,当你进入那个目录时它会自动切换。它还与 Rubymine 和其他支持 Ruby 的 IDE/编辑器集成。
解决方案 2:
将 GEM_PATH
环境变量设置为其中一个位置。这会覆盖其他所有内容,因此它至少会停止在多个地方查找。
方案三(应用加载优化):
您可能会考虑的一点是,如果您使用的是 bundler ,您可能只想在需要时才需要特殊用途的 gem。例如,如果您在应用程序的一个模块中使用 curb gem,请将其添加到加载模块的文件顶部:
require 'curb'
并更改您的 Gemfile,使行加载路缘看起来像这样:
gem 'curb', require: false
应用启动时加载的 gem 越少,加载速度就越快。自动要求功能很棒,但经常被遗忘和认为是理所当然的。它能带来的变化令人惊讶。
关于ruby - 由于 GEM_HOME 的要求,启动 Ruby 应用程序非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33371068/