为什么我的宝石需要这么长时间才能加载?

时间:2012-05-17 05:20:39

标签: ruby rubygems

我正在开发我的第一个名为t_time_tracker的宝石(哇哦!)。一切都在发展中很好;我尽可能地尽可能地缩短执行时间,以尽可能少地执行:

t_time_tracker[master*]% time ruby -Ilib ./bin/t_time_tracker 
You're not working on anything
0.07s user 0.03s system 67% cpu 0.141 total

(这是我的应用程序的“hello world” - 没有参数调用它只打印出“你没有做任何事情”)

大约十分之一秒,使用67%的CPU - 很酷,我可以忍受。感觉相当瞬间。让我们建立它:

$ gem build t_time_tracker.gemspec
$ gem install ./t_time_tracker-0.0.0.gem

使用已安装的二进制文件执行完全相同的操作:

$ time t_time_tracker
You're not working on anything
t_time_tracker  0.42s user 0.06s system 93% cpu 0.513 total
半秒钟?!那个是从哪里来的?!让我们添加一些调试输出,并包含开发二进制文件中的系统gem,以查看瓶颈所在:

t_time_tracker[master*]% time ruby ./bin/t_time_tracker  
(starting binary)
(require 'time' and 'optparse')
0.041432
(before `require 't_time_tracker')
0.497135
(after `require 't_time_tracker')
(Gem.loaded_specs.keys = t_time_tracker)
(initializing TTimeTracker class)
You're not working on anything
ruby ./bin/t_time_tracker  0.44s user 0.07s system 91% cpu 0.551 total

好吧,所以`require't_time_tracker'线似乎是罪魁祸首。让我们再次尝试将其缩小范围:

$ irb
>> t=Time.now; require 't_time_tracker'; puts Time.now-t
0.046792
=> nil

...什么?但这只需要半秒钟!让我们尝试用我们的调试输出构建gem:

$ gem build t_time_tracker.gemspec
$ gem install ./t_time_tracker-0.0.0.gem
$ time t_time_tracker
(starting binary) <---noticeable half second delay before this line shows up
(require 'time' and 'optparse')
0.050458
(before `require 't_time_tracker')
0.073789
(after `require 't_time_tracker')
(Gem.loaded_specs.keys = t_time_tracker)
(initializing TTimeTracker class)
You're not working on anything
t_time_tracker  0.42s user 0.06s system 88% cpu 0.546 total

所以,这0.5秒延迟来自哪里?我通常不在乎,但这是我每天要打五十次来更新我正在做的事情。 50 * 0.5秒* 365天* 70年= 15天失去生命。

系统信息:

Mac OS X 10.7.3。 2 GHz Intel Core 2 Duo。 4 GB内存。 ruby 1.9.2p290。

% gem -v
1.8.10<---noticeable half second delay before this line shows up
% gem list | wc -l
209

3 个答案:

答案 0 :(得分:2)

我看了这一段时间已经有一段时间了,但RubyGems在过去(也许是现在)花了很长时间才加载主要有两个原因:

  • 它会通过'yaml'加载许多相对昂贵的库,如'time'。通常你不在乎,因为它相对于ruby本身来说比较慢,与许多脚本的运行时间相比并不慢。
  • 它将扫描所有已安装的gem并将最新的gemspec加载到内存中。如果你有很多宝石,这需要很长时间。

这些问题可能会或可能不会发挥作用。但是,总是从RubyGems中获得一些开销。如果您真的需要性能,那么只需自己设置加载路径!如你所知,没有RubyGems的Ruby非常快。

要查看宝石的安装位置:

gem list -d YOUR_GEM_NAME

您将看到安装目录。您的宝石将位于INSTALL_DIR / gems / GEM_NAME-VERSION,请尝试执行:

time ruby -IINSTALL_DIR/gems/GEM_NAME-VERSION/lib INSTALL_DIR/gems/GEM_NAME-VERSION/bin/t_time_tracker

这很多,但你应该能够将它包装在一个单独的脚本中,就像这样(将其命名为t_time_tracker):

#!/usr/bin/env ruby -IINSTALL_DIR/gems/GEM_NAME-VERSION/lib
load 'INSTALL_DIR/gems/GEM_NAME-VERSION/bin/t_time_tracker'

然后:

chmod +x t_time_tracker
time ./t_time_tracker

将该文件放在PATH的任何位置。 RubyGems会自动为您服务,但当然您接受RubyGems的开销。

答案 1 :(得分:0)

宝石中使用的$LOAD_PATH可能是罪魁祸首。理想情况下,lib文件夹的路径首先在该阵列上。

答案 2 :(得分:-1)

可能是因为你有“来自本地”的宝石。因此,红宝石必须在他接他之前检查其他路径。

例如。如果您在执行

时将全局安装名为json.rb和gem的文件称为json
require 'json' 

他将找到第一个宝石并加载它:)。最后加载本地路径。如果您要捆绑宝石并安装,您将看到巨大的速度提升只是因为宝石中的不同位置。我不担心开发中缺乏加载时间。