Почему мой драгоценный камень так долго загружается?
Я разрабатываю свой первый драгоценный камень под названием t_time_tracker (woohoo!). Все развивалось хорошо; Я оплотировал его настолько, насколько мог, чтобы сократить время выполнения до минимально возможного:
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
(это "привет мир" моего приложения - вызов его без параметров, которые просто распечатываются "Вы ничего не работаете" )
Около десятой доли секунды и использует 67% моего процессора - круто, я могу жить с этим. Он чувствует себя довольно мгновенно. Пусть построит его:
$ 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
Полсекунды?! Откуда это пришло?! Добавьте дополнительный вывод отладки и включите системный жемчуг из двоичного файла разработки, чтобы узнать, где находится узкое место:
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 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 ГГц Intel Core 2 Duo. 4 ГБ оперативной памяти. ruby 1.9.2p290.
% gem -v
1.8.10<---noticeable half second delay before this line shows up
% gem list | wc -l
209
Ответы
Ответ 1
Прошло некоторое время с тех пор, как я посмотрел на это, но RubyGems в прошлом (и, может быть, настоящем) занял много времени, чтобы загрузить главным образом две причины:
- Он загрузил бы многие относительно дорогие библиотеки, такие как "время" через "yaml". Обычно вам все равно, потому что он медленный по отношению к рубину сам по себе, не медленный по сравнению с временем выполнения многих сценариев.
- Он сканирует все установленные камни и загружает последние данные gemspecs в память. Это заняло много времени, если у вас много драгоценных камней.
Эти проблемы могут или не могут быть воспроизведены. Однако вы всегда будете иметь некоторые накладные расходы от RubyGems. Если вам действительно нужна производительность, просто настройте свой путь загрузки самостоятельно! Ruby без RubyGems очень быстро, как вы знаете.
Чтобы узнать, где установлен ваш камень:
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
Это много, но вы можете обернуть это в отдельный script, что-то вроде этого (назовите его 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.
Ответ 2
Возможно, это потому, что у вас есть это "от локального" драгоценного камня. Так что рубину придется проверять другие пути, прежде чем он его поднимет.
например. если у вас будет файл json.rb и gem, установленный глобально под названием json при выполнении
require 'json'
он найдет первый драгоценный камень и загрузит его:). Локальный путь загружается последним. Если вы соберете драгоценный камень и установите его, вы увидите значительное улучшение скорости только из-за разного расположения в драгоценных камнях. Я бы не стал беспокоиться об этом отсутствии времени загрузки в разработке.
Ответ 3
$LOAD_PATH
, используемый в вашем драгоценном камне, скорее всего, станет виновником. В идеале путь к вашей папке lib
начинается с этого массива.