我目前正在研究一个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),然后输出它的版本号(命令gem的默认功能)。
我删除了我的整个gem主目录,并再次运行测试,它立即更快,但我可以看到它再次查看那些少数宝石(像指挥官这样的依赖),但“只是”几千次出现而不是3.5密耳。
我的宝石env看起来像这样:
- 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正在遍历我的整个加载路径,以满足一些依赖关系。这很好,但这只是变得越来越糟糕。 有人知道发生了什么事吗?我怀疑这不是想要/默认的行为吗?
有人知道发生了什么吗?我怎么能加快速度呢?
答案 0 :(得分:4)
有很多方法可以解决这个问题,包括我赢得的gemrc文件。我将提到你的一些选择:
解决方案1:
另一个答案是正确的,但我想对这个主题进行一些扩展,因为它是人们似乎经常面对的问题。 RVM可以提供帮助。一个特殊的功能是为此,gemsets。我个人已经搬到了rbenv并没有回头。与RVM相比,Rbenv对您的环境的干扰要小得多,但它们都很棒。您可以在RVM和rbenv中使用gemsets来限制应用程序可用的gem。您也可以制作特定于应用的宝石。使用gemset,您的应用程序将在一个位置查看并仅加载已使用的gem。它不会与其他应用程序gemsets混合使用。关于它的最好的事情是自动的,你只需要设置一次,当你在该目录时它会自动切换。它还与Rubymine和其他支持Ruby的IDE /编辑器集成。
解决方案2:
将GEM_PATH
环境变量设置为其中一个位置。这会覆盖其他所有内容,因此它至少会停止在多个位置查看。
解决方案3(应用加载优化):
您可能会想到的是,如果您使用的是捆绑器,您可能只需要在需要时使用特殊的宝石。例如,如果您在应用程序的一个模块中使用curb gem,请将其添加到加载模块的文件顶部:
require 'curb'
并更改您的Gemfile,以便行加载限制如下所示:
gem 'curb', require: false
您的应用启动时加载的宝石越少,加载的速度就越快。自动要求功能很棒,但经常被遗忘并被视为理所当然。它可以带来惊人的差异。
答案 1 :(得分:1)
I would suggest using rvm for ruby version and gem management. With rvm you can create application specific gemsets and ruby versions.
I hope this will solve your problem.