Shiny happy people coding

Codons avec le sourire

Each vs For

| Comments

En codant avec un ami, je lui ai fait la réflection qu’en ruby, il était plus rubyiesque d’utiliser le système de block et la méthode each sur un list plutôt que d’utiliser une boucle for à la Java comme il voulait le faire.

Partant de cette interrogation, je me suis demandé quel pouvait bien être la méthode réellement la plus rapide ?

Pour tester ce genre d’allégation, rien de mieux qu’un petit script ruby et un bon benchmark pour être sûr de ce qu’il en est réellement. J’ai donc utilisé le script suivant pour faire mon benchmark :

#! /usr/bin/ruby -w

require 'benchmark'

a = 1
n = 5_000_000
b = []
n.times { b << a; a+= 1;}
Benchmark.bmbm(10) do |x|
  x.report("each{}") { b.each { |r| r + 1}}
  x.report("each do end") {b.each do |r| r + 1; end}
  x.report("for do end") {for r in b do r + 1; end}
end

Voici les résultats que j’ai obtenu :

Sur un INSPIRON 1300 avec les caractéristiques suivantes :

  • Processeur : Intel(R) Pentium(R) M processor 1.70GHz
  • Memoire RAM : 508636 kB
  • Distribution : Debian/Linux
  • ruby : ruby 1.8.6 (2007-03-13 patchlevel 0) [i486-linux]
concerto-linux-15:06:50:~$ ./bench_boucle.rb 
Rehearsal -----------------------------------------------
each{}        5.060000   1.060000   6.120000 (  6.584567)
each do end   5.140000   0.980000   6.120000 (  6.149548)
for do end    4.620000   1.060000   5.680000 (  5.720802)
------------------------------------- total: 17.920000sec

                  user     system      total        real
each{}        5.030000   1.080000   6.110000 (  6.542022)
each do end   5.020000   1.100000   6.120000 (  6.137550)
for do end    4.600000   1.080000   5.680000 (  5.700844)

Sur un HP Pavilion ze4900 avec les caractéristiques suivantes :

  • Processeur : Intel(R) Pentium(R) M processor 1.50GHz
  • Memoire RAM : 481108 kB
  • Distribution : Gentoo/Linux
  • ruby : ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-linux]
shingara@shalamarette ~ $ ./bench_boucle.rb 
Rehearsal -----------------------------------------------
each{}        2.900000   0.000000   2.900000 (  2.897030)
each do end   2.840000   0.000000   2.840000 (  2.873575)
for do end    2.360000   0.010000   2.370000 (  2.355282)
-------------------------------------- total: 8.110000sec

                  user     system      total        real
each{}        2.870000   0.000000   2.870000 (  2.876499)
each do end   2.870000   0.000000   2.870000 (  2.882328)
for do end    2.350000   0.000000   2.350000 (  2.747947)

Finalement en regardant ces résultats, nous pouvons constater que la méthode la plus rapide semble être le for, alors que c’est vrai que ma première impression aurait été que le each serait plus rapide que le for. Une fois de plus, il n’y a vraiment que les test qui permettent de savoir exactement ce qui est plus ou moins rapide.

L’autre petite remarque que nous pouvons faire sur ce benchmark est la différence entre {} ou le do end. En effet nous pouvons constater qu’il n’y a absolument aucune incidence sur la performance. Cela ne sert vraiment qu’à la priorisation de l’un par rapport à l’autre.