14

我正在开发我的第一个 gem,称为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 中再次尝试以进一步缩小范围:

$ 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 次来更新我正在做的事情的事情。50 * 0.5 秒 * 365 天 * 70 年 = 失去生命的 15 天。

系统信息:

Mac OS X 10.7.3。2 GHz 英特尔酷睿 2 双核。4 GB 内存。红宝石 1.9.2p290。

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

3 回答 3

2

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

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

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

要查看 gem 的安装位置:

gem list -d YOUR_GEM_NAME

您将看到安装目录。您的 gem 将位于 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 的开销。

于 2012-07-12T16:03:33.523 回答
0

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

于 2012-05-31T06:59:49.973 回答
-1

这可能是因为您拥有“来自本地”的宝石。所以 ruby​​ 在接他之前必须检查其他路径。

例如。如果您在执行时将有名为 json.rb 的文件和全局安装的 gem 称为 json

require 'json' 

他会找到第一个宝石并加载它:)。最后加载本地路径。如果您将 gem 捆绑并安装,您将看到由于 gem 中的不同位置而大大提高了速度。我不会担心开发中缺少加载时间。

于 2012-05-30T08:49:11.640 回答