Verbesserte Ruby Performance

Für Ruby 1.9.3 sind diverse Performance Tweaks bekannt die jedoch in der standard RVM Version nicht vorhanden sind. Dieser Blogpost wird aufzeigen wie man diese auf einem Citrin Rails Server anwendet.

Die Optimierungen zusammengefasst

  • GCC Flags für Binary Optimization
  • Falcon patch
  • Ruby 1.9.3 Environment Variabeln

Die Auswirkungen und Performance Messungen findet man in den Quellen. Hier wird nur die Anwendung auf einem Rails Server gezeigt.

Als Beispiel nehmen wir das auf einem Rails Server Standard gehostete vereine.ch. Hier haben die Tweaks einen Performance Gewinn von 20%-30% über die 5 meist genutzten URLs gebracht.

Ruby ruby-1.9.3-p327 mit Optimierungen installieren

Zuerst kommt das Update auf die aktuelle RVM Version.

rvm get head --auto
rvm reload

Nun kann man Datei ~/.rvmrc erstellen mit dem Inhalt

rvm_configure_env=(CFLAGS="-march=native -O3")

Nun noch automake installieren und danach die neue Ruby Version mit dem Patch kompilieren.

aptitude install automake
rvm install 1.9.3-p327 --patch falcon

Um einen reibungslosen Übergang für die bestehenden Apps zu garantieren kann man das gemset der alten Ruby version in die neue kopieren.

rvm gemset copy ruby-1.9.2-p290 ruby-1.9.3-p327

Nun noch das Passenger Apache Modul unter der neuen Version kompilieren.

 rvm use ruby-1.9.3-p327
 passenger-install-apache2-module 

Danach noch den Passenger auf die richtige Ruby version konfigurieren:
In /etc/apache2/mods-enabled/passenger.load und /etc/apache2/mods-enabled/passenger.conf z.B.

   PassengerRoot /usr/local/rvm/gems/ruby-1.9.3-p327/gems/passenger-3.0.9
# PassengerRoot /usr/local/rvm/gems/ruby-1.9.2-p290/gems/passenger-3.0.9

Nach dem Webserver Neustart verwenden alle Rails Applikationen das neue Ruby.

service apache2 restart

Ruby Umgebungsvariabeln

Mit einem besseren Memory Allocator kann nochmal mehr Performance rausgeholt werden.

apt-get install libtcmalloc-minimal0
export LD_PRELOAD=/usr/lib/libtcmalloc_minimal.so.0.1.0

Zudem kann man in Ruby 1.9.3 das Verhalten des GC und mehr über Umgebungsvariabeln optimieren

export RUBY_HEAP_MIN_SLOTS=800000
export RUBY_HEAP_FREE_MIN=100000
export RUBY_HEAP_SLOTS_INCREMENT=300000
export RUBY_GC_MALLOC_LIMIT=79000000
export RUBY_FREE_MIN=200000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1.8

Mit einem Wrapperscript kann man diese auch für die vom Passenger gestarteten Ruby Prozesse verfügbar machen.

vi /usr/local/my_ruby_wrapper_script

Das Script soll so aussehen.

#!/bin/sh
export RUBY_HEAP_MIN_SLOTS=800000
export RUBY_HEAP_FREE_MIN=100000
export RUBY_HEAP_SLOTS_INCREMENT=300000
export RUBY_GC_MALLOC_LIMIT=79000000
export RUBY_FREE_MIN=200000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1.8
export LD_PRELOAD=/usr/lib/libtcmalloc_minimal.so.0.1.0
exec "/usr/local/rvm/wrappers/ruby-1.9.3-p327/ruby" "$@"

Nun noch ausführbar machen…

chmod +x /usr/local/my_ruby_wrapper_script

und in der Passenger Konfiguration angeben indem man in /etc/apache2/mods-enabled/passenger.conf

   PassengerRoot /usr/local/rvm/gems/ruby-1.9.3-p327/gems/passenger-3.0.9

ersetzt mit

   PassengerRuby /usr/local/my_ruby_wrapper_script