2012-05-17 4 views
14

Pracuję nad moim pierwszym klejnotem o nazwie t_time_tracker (woohoo!). Wszystko szło świetnie w rozwoju; I optomized to tak samo jak ja ewentualnie mogli, aby skrócić czas wykonywania dół tak mało jak to możliwe:Dlaczego mój klejnot ładuje się tak długo?

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 

(jest to „Hello World” z mojej aplikacji - nazywając go bez parametrów po prostu wypisuje „Ty” nie pracujesz na niczym ")

O jedną dziesiątą sekundy i wykorzystuje 67% mojego procesora - cool, mogę z tym żyć. Czuje się dość natychmiastowo. Zbudujmy go:

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

i robić dokładnie to samo z zainstalowanym binarny:

$ time t_time_tracker 
You're not working on anything 
t_time_tracker 0.42s user 0.06s system 93% cpu 0.513 total 

pół sekundy ?! Skąd to pochodzi?! Dodajmy wyjście debugowania i obejmują gem z systemu binarnego rozwoju, aby zobaczyć, gdzie wąskim gardłem jest:

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 

porządku, więc wymagają linia `„t_time_tracker”wydaje się być winowajcą. Spróbujmy jeszcze raz w irb, aby go zawęzić:

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

... co? Ale to trwało tylko pół sekundy! Spróbujmy zbudować klejnot z naszym wyjściem debugowania:

$ 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 

Tak, skąd pochodzi opóźnienie 0,5 sekundy? Zwykle nie obchodzi mnie to, ale to jest coś, co dzwonię około pięćdziesięciu razy dziennie, aby zaktualizować to, co robię. 50 * 0,5 sekundy * 365 dni * 70 lat = 15 dni straconego życia.

Informacje o systemie:

Mac OS X 10.7.3. 2 GHz Intel Core 2 Duo. 4 GB pamięci RAM. rubin 1.9.2p290.

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

Jaka jest wydajność podobna do wersji 1.9.3? –

+0

Interesujące ... 'rvm 1.9.3 && gem install t_time_tracker' daje mi mój super szybki czas wykonania (łącznie 0,100 sekund), ale jestem podejrzany, że to tylko dlatego, że' gem list | wc -l' = 7. Hmmm ... – cgenco

+0

Po 'gem install szynach',' gem lista | wc -l' = 33, a "czas t" to średnio około 0,21. Czy rozwiązanie "po prostu nie instaluj wielu klejnotów"? – cgenco

Odpowiedz

2

Dawno Patrzyłem na to, ale RubyGems został w przeszłości (a może teraźniejszości), zajęło dużo czasu, aby załadować na głównie z dwóch powodów:

  • Byłoby załadować wiele stosunkowo drogich bibliotek jak "czas" przez "yaml". Zwykle nie obchodzi cię to, ponieważ jest powolny w stosunku do rubinu sam, nie powolny w porównaniu do czasu wykonywania wielu skryptów.
  • Skanowałby on wszystkie zainstalowane klejnoty i wczytał najnowsze pliki gemspec do pamięci. To zajęło dużo czasu, jeśli masz dużo klejnotów.

Te problemy mogą nadal być lub nie być w grze. Jednak zawsze będziesz mieć pewien koszt z RubyGems. Jeśli naprawdę potrzebujesz wydajności, po prostu ustaw ścieżkę ładowania samodzielnie! Ruby bez RubyGems jest bardzo szybki, jak wiesz.

Aby zobaczyć, gdzie zainstalowana jest gem:

gem list -d YOUR_GEM_NAME 

Zobaczysz katalogu instalacyjnego. Twój skarb będzie w Install_Dir/kamienie/GEM_NAME wersja więc spróbuj wykonanie:

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

To dużo, ale powinieneś być w stanie owinąć to w osobnym skrypcie coś takiego (nazwa go 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' 

Następnie:

chmod +x t_time_tracker 
time ./t_time_tracker 

I umieścić ten plik w dowolnym miejscu wzdłuż PATH. RubyGems robi to automatycznie, ale oczywiście akceptujesz obciążenie RubyGems.

+0

Świetnie, ale co powiesz na klejnot, który jest dystrybuowany do innych użytkowników? – sixty4bit

0

Jest to prawdopodobnie dlatego, że masz "od miejscowego" klejnot. Ruby będzie musiał sprawdzić inne ścieżki, zanim go odbierze.

np. jeśli trzeba będzie plik o nazwie json.rb i zainstalowane klejnot zwany globalnie json, gdy robi

require 'json' 

znajdzie pierwszy gem i załadować go :). Lokalna ścieżka jest ostatnio ładowana. Jeśli połączysz klejnot i zainstalujesz, zauważysz znaczną poprawę prędkości właśnie z powodu innej lokalizacji klejnotów. Nie martwiłbym się zbytnio tym brakiem czasu ładowania w fazie rozwoju.

0

$LOAD_PATH wykorzystywane w swoim gem może być winowajcą. Idealnie ścieżka do twojego katalogu lib jest pierwsza w tej tablicy.