Wstęp

Tytułem wstępu powiem, że artykuł nie jest mój. Ostatnio korespondowałem trochę z Xavierem Shay i pojawił się pomysł tłumaczenia co ciekawszych wpisów na język polski - tak z myślą o młodych Railsowcach - zawsze to łatwiej zrozumieć w swoim języku. Chciałbym zaznaczyć, że nie jestem profesjonalnym tłumaczem i nie wszystko może być idealnie. Oryginał artykułu możecie znaleźć tutaj.

Wolno, wolniej, najwolniej...

Szybkość ładowania plików maleje jeśli chodzi o kolejne wersje Rubiego. Można to zaobserwować na poniższym wykresie:

Dla przykładu, nasza średniej wielkości aplikacja wymaga około 2200 plików. Zaczyna być to problematyczne, ponieważ dla Railsów 1.9.2 start aplikacji trwa około 20 sekund, zaś dla 1.9.3 ponad 46 sekund. Obie te wartości są zdecydowanie zbyt wysokie.

Dlaczego tak się dzieje? Powodów jest kilka, niemniej jednak jednym z głównych powodów jest algorytm includowania plików, który wygląda mniej więcej tak:

def require(file)
 $loaded.each do |x|
   return false if x == file
 end
 load(file)
 $loaded << file
end

Jak nietrudno zauważyć, tego typu pętla zwalnia wraz z każdym nowym plikiem. Aby temu zaradzić napisałem patch do 1.9.3 który zmienia ten algorytm aby wyglądał tak:

def require(file)
  return false if $loaded[file]
  load(file)
  $loaded[file] = true
end

Po tej zmianie, prędkości ładowania prezentują się następująco:

Dużo lepiej.

Wprawdzie jest to tylko benchmark, jednak moja główna Railsowa aplikacja ładuje się około 10 sekund (20 przy Rubym 1.9.2). Pusta aplikacja ładuje się około 1.1 sekund. Jest to mniej niż w 1.8.7.

Instalacja poprawki

Oto krótka instrukcja jak zainstalować z wykorzystaniem RVMa (w zaledwie 10 minut) moją poprawkę.

# Benchmark testowy
cd /your/rails/app
time script/rails runner "puts 1"

# Instalacja spatchowanego Rubiego
curl https://gist.github.com/raw/996418/e2b346fbadeed458506fc69ca213ad96d1d08c3e/require-performance-fix-r31758.patch > /tmp/require-performance-fix.patch
rvm install ruby-head --patch /tmp/require-performance-fix.patch -n patched
# ... czeeeekamy :)

# Test porównawczy
cd /your/rails/app
rvm use ruby-head-patched
gem install bundler --no-rdoc --no-ri
bundle
time script/rails runner "puts 1"

Chcesz pomóc?

Zanim poprawka ta zostanie umieszczona w trunku, potrzeba jeszcze wiele wysiłku. Doceniłbym gdybyście:

  • sprawdzili ten kod i zostawili komentarz z wynikami
  • przejrzeli ten patch
  • sprawdzili to na Windowsie
  • zgłaszali ew. błędy

Co dalej?

Zdaję sobie sprawę, że do dołączenia tego do 1.9.3 jeszcze daleka droga. Niemniej jednak jest to pierwszy z wielu kroków w drodze do przyśpieszenia Railsów. Wciąż mamy Bundlera oraz RubyGems które robią... coś - coś co chciałbym sprawdzić. Chciałbym też przeportować ew. zmiany także do JRubiego.