ruby - 由于 GEM_HOME 的要求,启动 Ruby 应用程序非常慢

标签 ruby

我目前正在开发一个 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/

相关文章:

ruby-on-rails - 打开终端时自动运行命令(Linux Mint 16)

ruby - 将字符分组以形成字符串

ruby - 使用纯 ruby​​ 存储数据的最佳方式,无依赖性

css - Watir - 使用 CSS 元素

javascript - 如何在 Watir 中引用 JavaScript 工具提示

ruby-on-rails - 在 ActiveSupport::Concern 中重载方法

ruby - 有没有一种简单的方法可以将数字转换为字符串中的 float ?

arrays - 当存在重复值时,如何比较数组中的整数索引?

ruby - 为什么 `puts(nil or 4)` 在 Ruby 中失败?

ruby - 在方法定义中使用 $1、$2 等全局变量