En ce moment je fais quelques recherches sur la lenteur de Ruby. J’aimerais faire un article sur pourquoi Ruby est lent et pourquoi ça n’est pas un problême la plupart du temps.

Pendant ces recherches je suis tombé sur cet article: Ruby Is Too Slow for Programming Competitions. Dans cet article, l’auteur utilise ce script de benchmark pour comparer deux manières différentes pour savoir si un nombre est un palindrome. La première manière utilise une méthode mathématique et la seconde manière transforme le nombre en chaîne de caractères.

Alors je n’ai pas regardé le code en détail, j’ai juste voulu faire tourner le benchmark sur quelques version de Ruby. On commence avec la version 1.9.3:

ruby MRI 1.9.3

Rehearsal -------------------------------------------------------------
Integer palindrome method  18.800000   0.000000  18.800000 ( 18.814018)
String palindrome method    9.860000   0.010000   9.870000 (  9.885368)
--------------------------------------------------- total: 28.670000sec

                                user     system      total        real
Integer palindrome method  18.150000   0.000000  18.150000 ( 18.168135)
String palindrome method    9.830000   0.000000   9.830000 (  9.844366)

On voit que la méthode qui utilise les nombres est deux fois plus lente que la méthode qui utilise les chaînes de caractères.

Passons à la version 2.0 de Ruby:

ruby MRI 2.0

Rehearsal -------------------------------------------------------------
Integer palindrome method  19.250000   0.010000  19.260000 ( 19.273625)
String palindrome method    8.910000   0.000000   8.910000 (  8.922845)
--------------------------------------------------- total: 28.170000sec

                                user     system      total        real
Integer palindrome method  19.560000   0.000000  19.560000 ( 19.555138)
String palindrome method    8.760000   0.100000   8.860000 (  8.866579)

Je ne m’attendais pas du tout à ça ! La seconde méthode est bien légèrement plus rapide mais la première méthode est au contraire légèrement plus lente qu’avec Ruby 1.9.3. Utilisant Ruby au quotidien, j’avais noté une réelle amélioration de la vitesse lors du passage à 2.0.

Maintenant voyons ce que donne la version 2.1:

ruby MRI 2.1

Rehearsal -------------------------------------------------------------
Integer palindrome method  13.930000   0.010000  13.940000 ( 13.938652)
String palindrome method    8.160000   0.000000   8.160000 (  8.165836)
--------------------------------------------------- total: 22.100000sec

                                user     system      total        real
Integer palindrome method  14.000000   0.000000  14.000000 ( 13.992662)
String palindrome method    8.320000   0.000000   8.320000 (  8.323284)

C’est plus conforme à mes attentes, on voit une nette amélioration avec la première méthode.

Comme j’ai un rubinius sous la main et que j’ai déjà pu constater que cette implémentation de Ruby pouvait être rapide, j’essaye:

rubinius 2.0

Rehearsal -------------------------------------------------------------
Integer palindrome method   3.768236   0.000000   3.768236 (  3.781376)
String palindrome method   10.240640   0.044002  10.284642 ( 10.293314)
--------------------------------------------------- total: 14.052878sec

                                user     system      total        real
Integer palindrome method   2.140134   0.000000   2.140134 (  2.141363)
String palindrome method    8.472530   0.048003   8.520533 (  8.533402)

Waow ! Si la seconde méthode (avec les chaînes de caractères) est sensiblement équivalente à Ruby 2.1, la première méthode (avec les nombres) est pratiquement 7 fois plus rapide.

De là à dire que les benchmarks ne servent à rien, il n’y a qu’un pas que je ne veux pas franchir. Je veux seulement dire qu’il faut faire très attention avec les benchmarks et ne pas tirer de conclusions hatives. L’auteur de ce benchmark concluait à tort que la seconde méthode est plus rapide que la première. Alors que c’est plus une question de contexte, d’algorithme utilisé, d’implémentation du langage, et peut-être encore d’autres choses qui m’échappent.

La seule conclusion que je peux tirer de ça est: d’une manière générale, pensez à tester votre application avec Rubinius, vous pourriez être agréablement surpris ;)

À demain.