Ruby 1.9 (YARV) vs. Python, Lua & PHP

Opublikowane przez Jarosław Zabiełło Mon, 01 Jan 2007 18:36:00 GMT

Korzystając z tego, że niedawno do repozytorium Rubiego został dodany YARV (wirtualna maszyna Rubiego) pokusiłem się o małe porównanie wydajności. Jako test użyłem prostego programu jaki pojawił się na liście pl.comp.lang.pyhon (musiałem tylko trochę zwiększyć pętle do 10 milionów iteracji, aby były widoczne jakieś wyniki) Użyty sprzęt: Athlon64 3700+, 64bit Ubuntu 6.0.6.

Sprawdziłem też z ciekawości PHP 5.2 na tym samym sprzęcie. Dla tak prostego testu powinien móc dać z siebie wszystko. Jest jednak wolniejszy od Rubiego 1.9.

Kod dla Pythona:

import time
t=time.time()
a=0
for i in xrange(10000000):
    a += i
print a
print time.time() - t
Kod dla Lua:
t = os.clock()
a = 0
for i = 1,10000000 do
    a=a+i
end
print(a)
print(os.clock() - t)

Kod dla Rubiego:

t = Time.now
a = 0
for i in 1..10_000_000
  a = a+i
end
puts a
puts Time.now - t

Kod dla PHP:

<?php
function microtime_float() {
 $time = microtime();
 return (double)substr($time, 11) + (double)substr($time, 0, 8);
}
$t =  microtime_float();
$a = 0;
for ($i = 0; $i < 10000000; $i++) {
  $a += $i;
}
print "$a\n";
print  microtime_float()- $t;
?>

Wyniki:

  1. Lua: 1.14 s
  2. Ruby 1.9: 1.49 s
  3. PHP 5.2: 1.74 s
  4. Python 2.5: 2.64 s
  5. Python 2.4.3: 2.72 s
  6. Ruby 1.8.5: 3.83 s.

Drugie podejście

Tym razem wynik uśredniam dla 10 prób. Zwiększyłem ilość iteracji do 20 mln. No i… Ruby 1.9 pobił wszystko. Zarówno Pythona jak i Lua! (PHP 5.2 po 30 sek. zgłosił timeout. Musiałem więc uśrednić po 5 wynikach.)

PYTHON

import time
def bench():
    a, t = 0, time.time()
    for i in xrange(20000000):
        a+=i
    return time.time()-t
result = 0
for i in range(10):
  result += bench()
print result / 10.0

RUBY

def bench
  a, t = 0, Time.now
  20_000_000.times { |i| a += i }
  Time.now - t
end
result = 0
10.times { |i| result += bench }
puts result / 10

LUA

function bench()
  a = 0
  t = os.time()
  for i = 1, 20000000 do
    a = a + i
  end
  return os.time() - t
end
result = 0
for x = 1,10 do
  result = result + bench()
end
print(result/10)

PHP

<?php
function bench() {
  $a = 0;
  $t =  time();
  for ($i = 0; $i < 20000000; $i++) $a += $i;
  return time() - $t;
}
$result = 0;
for ($x = 1; $x <= 5; $x++) $result += bench();
print $result / 5.0;
?>

Wyniki

  1. Ruby 1.9: 2.0953268 s.
  2. Lua 5.1: 2.4 s.
  3. Python 2.5: 2.49481592178 s.
  4. Python 2.4.3: 2.71687791348 s.
  5. PHP 5.2: 4.2 s.
  6. Ruby 1.8.5: 9.0153751 s.

Jestem ciekaw kiedy wyjdzie Rails dostosowany do Ruby 1.9. Zapowiada się bardzo obiecująco!

Posted in , ,  | Tagi , , , , ,  | 19 comments

Comments

  1. Avatar dr_bonzo powiedział 39 minutes later:

    Z tego wyglada ze 1.9 jest szybszy o ok 0.6 koszmaru :D

  2. Avatar Jarosław Zabiełło powiedział about 5 hours later:

    No, niektórzy mówili tak, z przesadą, o “koszmarnej” wydajności. :) Może wydajność nie była nigdy koszmarna, ale na pewno wyraźniej wolniejsza od Pythona. Teraz, dzięki YARV to się radykalnie poprawiło. Już wcześniej można było czytać o poprawie wydajności nawet do 10x (zależy co testować). Ale nie wiadomo było kiedy będzie można było jakoś używać YARV. No i niespodzianka, YARV jest w trunk SVN dla Rubiego 1.9.x. Zatem skompilowałem, zapuściłem test i wyniki są jakie są. :)

  3. Avatar Drogomir powiedział about 7 hours later:

    Ja tylko wspomnę tak trochę offtopicowo, że w php.ini można zmienić maksymalny czas wykonywania skryptu – domyślnie to właśnie 30s.

  4. Avatar Azzazael powiedział about 17 hours later:

    PHP 5.14 – 2.6s dla 2 mln (drugi kod). Test wydaje mi się mocno naciągany i niewiarygodny na korzyść Rubiego. Panie Jarku – nie jest Pan obiektywny. Ruby fajna sprawa, ale warto przeprowadzać testy rzetelnie. :)

  5. Avatar slaug powiedział about 18 hours later:

    A ja tylko dodam, że w tytuł można by zmienić na ‘porównanie pętli for w językach…’.

    Poza tym zwróć uwagę, że dla Ruby’ego używasz specjalnie pod niego skonfigurowaną wirtualną maszynę, a dla php zapewne w miarę standardowej wersji apacha.

    Jak dla mnie to porównanie nic nie mówi o faktycznej szybkości języków.

  6. Avatar Rafał Wysocki powiedział about 18 hours later:

    Moją uwagę zwróciło to, że w drugim teście wyniki dla pythona zmieniły się minimalnie, a python2.5 wykonał pętle dłuższą szybciej niż krótszą. Trochę to dziwne.

  7. Avatar slaug powiedział about 19 hours later:

    Link do benchmarka

    http://shootout.alioth.debian.org/debian/benchmark.php?test=all&lang=ruby&lang2=php

  8. Avatar lopex powiedział about 22 hours later:

    ten wynik to zasługa OPT_SPECIALISED_INSTRUCTION (czyli olanie niezredefiniowanej metody Fixnum#+), niedługo będzie jeszcze lepiej…

  9. Avatar Drogomir powiedział about 23 hours later:

    Chyba nie rozumiecie sensu tego testu. Nikt przecież nie twierdzi, że ten test jest miarodajny i testuje ogólną wydajność języków. Chodzi o sam fakt – wersja Rubiego 1.8.5 jest sporo wolniejsza od PHP i Pythona, a wersja 1.9 z przepisanym VM szybsza. Trzeba poczekać na jakieś bardziej rozbudowane testy – to pokazuje tylko, że rozwój Rubiego idzie w dobrą stronę

    YARV to jest po prostu inna wirtualna maszyna, inna implementacja. Matz pisząc swój interpreter nie stawiał tak bardzo na szybkość. Do listopada 2007 Ruby z YARV’em ma być już w stabilnej oficjalnej wersji, więc nie nazywałbym tego “specjalnie pod niego skonfigurowaną wirtualną maszyną”. :)

  10. Avatar lopex powiedział 1 day later:

    Dokładnie, wraz z ze wzrostem stabilności i funkcjonalności będzie więcej wiadomo. Wydajność (prawie) nigdy nie była brana pod uwagę przy projektownaniu Rubiego (większe optymalizacje zaczęły się dopiero jakies 5 lat temu – 1.6 to był koszmar). Z drugiej strony implementacja Fixnuma to jedno ze sprytniejszych oszustw wziętych żywcem z lispa (tagowanie wskaźników). YARV zawsze był tworzony specjalnie dla Rubiego – w końcu to Yet Another Ruby Virtual machine…

  11. Avatar Jarosław Zabiełło powiedział 1 day later:

    Azzazael: nie podałeś sprzętu jaki użyłeś i dałeś 10x mniej interacji. Ja testowałem dla 20mln, a nie 2mln.

    Rafał Wysocki: trudno uzyskać identycznych (co do milisekundy) wyników, bo na tym serwerze też chodzą jakieś programy. Dlatego, wynik to uśredniona wartość po 10 próbach.

  12. Avatar lopex powiedział 1 day later:

    http://www.rubychan.de/share/yarv_speedups.html

  13. Avatar slaug powiedział 1 day later:

    Drogomir: przeczytaj tytuł tego artykułu, a potem mów o sensie. Ja tylko napisałem, że jest on nieadekwatny do treści.

    Nie twierdzę, że Ruby nie idzie w dobrą stronę, tylko autor albo powinien zająć się analizą postępów Ruby’ego, albo przygotować rzetelne testy porównawcze.

  14. Avatar hax0r na patyk00 powiedział 1 day later:

    Uśrednianie wyników w takich testach jest złe. Lepiej zrobić te 20 powtórzeń i dla każdego języka wziąć najlepszy wynik, to ma większy sens wg. mnie.

  15. Avatar dr_bonzo powiedział 2 days later:

    function microtime_float() { $time = microtime(); return (double)substr($time, 11) + (double)substr($time, 0, 8); }

    Przeciez jest microtime( true ) , ktore zwraca floata (dostepne w php5+) :D

  16. Avatar __doc__ powiedział 4 days later:

    These tests are saying nothing really. Do yourself the favor of doing proper comparision next time please, that would include things like function call speed, class features, recursion, mathematical expression, closures, etc. There are many many tests you can apply. a+=1 isn’t very conclusive.

  17. Avatar Jarosław Zabiełło powiedział 4 days later:

    doc: It was not intended to be comprehensive. It was only a simple try. I have added also second test, when Python is faster.

  18. Avatar ja powiedział 5 days later:

    to może zrób trzeci test w którym java bedzie najszybsza

  19. Avatar Jarosław Zabiełło powiedział 5 days later:

    A co mnie jakaś Java obchodzi? Może jeszcze test assemblera, co? Interesowało mnie tylko porównanie wybranych języków dynamicznych, wysokopoziomowych.

(leave url/email »)

   Pomoc języka formatowania Obejrzyj komentarz