Ruby, Python i natywne wątki systemu operacyjnego

Opublikowane przez Jarosław Zabiełło Sat, 26 Jul 2008 11:22:00 GMT

Wiele się mówi o tym, że Ruby jak i Python nie posiadają obsługi natywnych wątków systemu operacyjnego. Wbudowane, tzw. green threads, nie są w stanie wykorzystać zalet maszyn wyposażonych w procesory wielordzeniowe. Istnieją jednak implementacje obu języków w czystej Javie. Czy ich użycie daje jakieś znaczące przyśpieszenie?

Wszystkie testy były wykonywane na MacBook Pro Core2 Duo 2.16GHZ, 4GB RAM i systemie Mac OS X 10.5.4 Leopard + zainstalowana Java 1.6.0_05.

Python

from time import time
from random import Random
from threading import Thread
rand = Random().randint # alias

class Test(Thread):
   def __init__ (self): 
      Thread.__init__(self)
      print "Starting %s" % self.getName()
   def run(self): 
      a = [rand(0,SIZE) for x in xrange(SIZE)]
      a.sort()
      print "%s finished" % self.getName()      

print "Start"
start = time()
THREADS, SIZE = 20, 100000
threads = []             
for i in xrange(THREADS):
    t = Test()
    threads.append(t)
    t.start()     
while True in [t.isAlive() for t in threads]:
    pass
print "Time: %s s" % (time() - start) 

Dla powyższego kodu Python i Jython uzyskały wyniki:

  • Jython 2.2.1 = 12.15 s.
  • Python 2.5.2 = 14.24 s.

Rożnica jakoś podejrzanie mała wskazująca na wciąż jeszcze niedojrzałą implementację Jythona. Dla pewności, zmodyfikowałem kod tak, aby korzystał z natywnych bibliotek Javy.

from time import time
from random import Random
rand = Random().randint # alias
from java.lang import Thread, Runnable

class Test(Runnable):
   def __init__ (self): 
      print "Starting %s" % self
   def run(self):         
      a = [rand(0,SIZE) for x in xrange(SIZE)]
      a.sort()  
      print "%s finished" % self

print "Start"
start = time()
THREADS, SIZE = 20, 100000    
threads = []             
for i in xrange(THREADS):
    t = Thread(Test())              
    threads.append(t)
    t.start()     
while True in [t.isAlive() for t in threads]:
    pass
print "Time: %s s" % (time() - start) 

Tym razem

  • Jython 2.2.1 = 11.96 s.

Różnica jest minimalna. Na dodatek panuje trochę zamieszania co do sposobu odpalania wątków w Jythonie – mętna składnia i za dużo możliwych sposobów uzyskania tego samego efektu. Po SQLAlchemy, Jython jest kolejnym przykładam całkowitej ignorancji założeń języka Python (o istnieniu jednej, oczywistej drogi do tego samego celu). Na domiar złego, mój pierwotny test zakładał testowanie miliona liczb do sortowania. Jython nie był w stanie tego testu wykonać z powodu braku pamięci dla Javy. Ruszył dopiero jak mu zaalokowałem 1GB (słownie: jeden gigabajt pamięci) za pomocą opcji (-Xmx1024M), co jest po prostu chore! Po wymianie pierwotnego range() na generatorowy xrange() zapotrzebowanie na pamięć wyraźnie zmalało i wystarczyła już opcja -Xmx256M. Jednakże kod się wykonywał tak koszmarnie wolno, że nie starczyło mi cierpliwości i zmniejszyłem ilość iteracji do 100 tys.

Ruby

require "time"
require "thread"

THREADS, SIZE = 20, 100_000

start = Time.now
puts "Start"
threads = (1..THREADS).map do |i|
  puts "Starting Thread-#{i}\n"
  Thread.new(i) do |t|
    a = (1..SIZE).map {|e| rand(SIZE)}
    a.sort!
    puts "Thread-#{t} ended\n"
  end
end
while t = threads.find {|lt| lt.alive?}
  t.join
end 
puts "Time: #{Time.now - start} s."

Pierwsze, co mi się od razu rzuca w oczy, to o wiele czytelniejsza, zgrzebniejsza składnia Rubiego, który tu korzysta z bloków kodu. Po drugie, wyniki są dosyć ciekawe:

  • Ruby 1.9.0 = 1.11 s
  • Ruby Enterprise = 2.77 s
  • JRuby 1.1.2 = 3.53 s
  • Ruby 1.8.7 = 21.82 s.

Ruby okazał się najwolniejszy w tym zestawieniu. Python był tylko trochę szybszy. JRuby, korzystający z javowych wątków systemowych, zdeklasował Rubiego, Pythona i niedojrzałego Jythona. Jednakże to nie JRuby okazał się tu zwycięzcą. Nie trzeba czekać na Ruby 2.0, wersja 1.9 posiada już natywną obsługę wątków POSIX i jest dodatkowo nieźle zoptymalizowana. Ruby 1.9 pokazał, że jest tu prawie 4x szybszy od JRuby. Nie sądzę, że tą szybkość uzyskał na lepszej implementacji wątków od Javy. Raczej ma mocno zoptymalizowany kod który był wykonywany w każdym z wątków.

Bardzo dobrze poradził sobie też Ruby Enterprise, zoptymalizowana wersja Ruby 1.8.6 przez twórców Passengera! Nie wiem jakim cudem Ruby Enterprise pobił JRubiego… no chyba, że jego twórcy dodali mu obsługę natywnych wątków systemu operacyjnego. Inaczej nie mogę sobie wytłumaczyć tak dobrego wyniku.

Updated

Dla pełniejszego obrazu uruchomiłem testy dla 1 wątku. Poprawiłem też błąd z ilością list do sortowania faworyzującą Rubiego. Ostateczne podsumowanie wygląda tak:

1 thread, 2,000,000 iterations

  1. Ruby 1.9 = 1.69 s.
  2. Ruby Enterprise = 3.38 s.
  3. JRuby 1.1.2 = 7.06 s.
  4. Jython 2.2.1 = 17.29 s.
  5. Python 2.5.2 = 18.06 s.
  6. Ruby 1.8.7 = 22.37 s.

20 threads * 100,000 iterations

  1. Ruby 1.9 = 1.54 s.
  2. Ruby Enterprise = 3.01 s.
  3. JRuby 1.1.2 = 5.82 s.
  4. Jython 2.2.1 = 11.86 s.
  5. Python 2.5.2 = 12.32 s.
  6. Ruby 1.8.7 = 22.68 s.

Czasy, kiedy Python był zawsze szybszy od Rubiego, to już przeszłość. Z wyników wynika, że to nie obsługa wątków zadecydowała o wynikach. Ruby 1.9 pobił wszystkich zarówno w teście 1 jak i wielu wątków.

Updated 2008-07-30

Poprawiłem trochę test, aby nie zużywał tyle pamięci. Wyrzuciłem więc generowanie list i sortownie. Zostało samo generowanie losowych liczb. Dodałem też kod dla Javy dla porównania.

Java

import java.util.Random;

public class Main {

  static Integer SIZE,  ITERATIONS;

  public static void main(String[] args) throws Exception {
    Integer[] threads_nr = {1, 10, 50, 100};
    SIZE = Integer.parseInt(args[1]);
    System.out.println(args[0]);
    for(Integer nr: threads_nr) {
      ITERATIONS = SIZE / nr;
      System.out.printf(" %3d thread(s) x %9s = ", nr, ITERATIONS);
      long start = System.currentTimeMillis();
      Thread[] threads = new Thread[nr];
      for(int i = 0; i < threads.length; i++) {
        threads[i] = new ThreadTest();
        threads[i].start();
      }
      while(threadsAlive(threads)) {}
      System.out.printf("%s s.\n", (System.currentTimeMillis() - start) / 1000.0);
    }
  }

  public static boolean threadsAlive(Thread[] threads) {
    for(Thread t: threads)
      if(t.isAlive())
        return true;
    return false;
  }

  static class ThreadTest extends Thread {

    @Override
    public void run() {
      Random rnd = new Random();
      for(int i = 0; i < ITERATIONS; i++)
        rnd.nextInt(SIZE);
    }
  }
}

Test:

$ java Main "`java -version`" 10000000
java version "1.6.0_05"
Java(TM) SE Runtime Environment (build 1.6.0_05-b13-120)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_05-b13-52, mixed mode)
  1 thread(s) x  10000000 = 0.361 s.
 10 thread(s) x   1000000 = 0.18 s.
 50 thread(s) x    200000 = 0.186 s.
100 thread(s) x    100000 = 0.189 s.  

Java, co nie dziwi, jest najszybsza. Nie ma znaczącej różnicy między 10 czy 10 wątkami, bo mój procesor posiada tylko dwa rdzenie.

Ruby/JRuby

require "time"
require "thread"

SIZE = ARGV[1].to_i  
puts ARGV[0]   
[1, 10, 50, 100].each do |nr|
  iterations = SIZE / nr
  print " %3d thread(s) x %9s = " % [nr, iterations]
  start = Time.now
  (1..nr).map do |i|
    Thread.new(i) do |t|
      iterations.times {rand(SIZE)}
    end
  end.each {|t| t.join}
  puts Time.now - start
end

Ten sam kod w Ruby/JRuby wygląda znacznie krócej (i ładniej) ale kosztem wydajności. To też nie dziwi. Ruby jest bardzo produktywnym językiem, lecz oczywiście nie tak szybkim jak Java.

Wyniki testów:

Ruby 1.9:

$ ruby1.9 main.rb "`ruby1.9 -v`" 10_000_000
ruby 1.9.0 (2008-06-20 revision 17482) [i686-darwin9.4.0]
  1 thread(s) x  10000000 = 2.858588
 10 thread(s) x   1000000 = 2.832928
 50 thread(s) x    200000 = 2.845377
100 thread(s) x    100000 = 2.852745

JRuby:

$ jruby main.rb "`jruby -v`" 10_000_000
jruby 1.1.3 (ruby 1.8.6 patchlevel 114) (2008-07-28 rev 6586) [x86_64-java]
   1 thread(s) x  10000000 = 3.58
  10 thread(s) x   1000000 = 3.4290000000000003
  50 thread(s) x    200000 = 3.442
 100 thread(s) x    100000 = 3.516

Ruby Enterprise:

$ ruby-enterprise main.rb "`ruby-enterprise -v`" 10_000_000
ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-darwin9.4.0]
  1 thread(s) x  10000000 = 3.510694
 10 thread(s) x   1000000 = 3.552756
 50 thread(s) x    200000 = 3.586885
100 thread(s) x    100000 = 3.574564

Ruby 1.8.6 (installed with Leopard):

$ /usr/bin/ruby main.rb "`/usr/bin/ruby -v`" 10_000_000
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
   1 thread(s) x  10000000 = 6.586917
  10 thread(s) x   1000000 = 6.78801
  50 thread(s) x    200000 = 6.951003
 100 thread(s) x    100000 = 6.907087

Ruby 1.8.7 (installed from MacPorts):

$ ruby main.rb   "`ruby -v`" 10_000_000
ruby 1.8.7 (2008-06-20 patchlevel 22) [i686-darwin9.4.0]
   1 thread(s) x  10000000 = 36.329174
  10 thread(s) x   1000000 = 36.808753
  50 thread(s) x    200000 = 36.715717
 100 thread(s) x    100000 = 36.499772   

To co niepokoi, to koszmarnie wolna praca Ruby 1.8.7 w porównaniu do Ruby 1.8.6. To jest bardzo podejrzana sprawa. Cieszy za to dobra wydajność Ruby Enterprise.

Python/Jython

from random import Random
from sys import argv
from time import time
from threading import Thread
rand = Random().randint # alias

class ThreadTest(Thread):
   def __init__ (self, iterations): 
      Thread.__init__(self)              
      self.iterations = iterations
   def run(self): 
      [rand(0,SIZE) for x in xrange(self.iterations)]

SIZE = int(argv[2])
print argv[1]
for nr in [10, 50, 100]:
  iterations = SIZE / nr
  print " %3d thread(s) x %9s = " % (nr, iterations),
  start = time()
  threads = []
  for i in range(nr):
     t = ThreadTest(iterations)
     threads.append(t)
     t.start()
  for t in threads:
     t.join()
  print "%s s." % (time() - start) 

Test:

$ python main.py "`python -V`" 10000000
Python 2.5.2
  1 thread(s) x  10000000 =  34.5188429356 s.
 10 thread(s) x   1000000 =  52.3496830463 s.
 50 thread(s) x    200000 =  53.9406650066 s.
100 thread(s) x    100000 =  58.3923280239 s.

Co ciekawe, Python 2.5.2 okazał się najwolniejszy. Im więcej wątków tym jeszcze wolniej działał. Był wolniejszy nawet od (dziwnie wolnego) Ruby 1.8.6. Ale, być może to jest wina bardzo wolnej biblioteki generowania losowych liczb. Ech, jak tu cokolwiek porównywać między językami jak takie odkrywa się takie babole w bibliotece standardowej Pythona.

Jython był jeszcze wolniejszy. Dla 10 mln. iteracji, mimo że nie były tworzone w pamięci żadne listy, wlókł się tak wolno, że przerwałem test. Po zmniejszeniu iteracji o rząd wielkości (do 1 miliona) uzyskał wyniki takie jak Ruby 1.8.6 dla 10 milionów iteracji. Jython jest najwyraźniej jeszcze bardzo słabo zoptymalizowany. Pomysły aby na nim odpalać frameworki takie jak Django, to na razie raczej przedwczesny pomysł.

Iterations: 1,000,000 instead of 10,000,000:

$ jython main.py "`jython --version`" 1000000
Jython 2.2.1 on java1.6.0_05

  10 thread(s) x    100000 =  6.391000032424927 s.
  50 thread(s) x     20000 =  4.368000030517578 s.
 100 thread(s) x     10000 =  4.352999925613403 s.

Tagi , , , ,  | 33 comments

Comments

  1. Avatar Jacek Becela powiedział about 6 hours later:

    Też jestem zaskoczony wynikami Ruby Enterprise. Ich implementacja (tak obiło mi się o uszy) różni się w miejscach związanych z obsługą pamięci, a Twój test prawdopodobnie (1GB dla Javy) testuje najbardziej właśnie ten aspekt działania interpretera / maszyny wirtualnej.

    Poza Ruby 1.8 wyniki są zbliżone, a to cieszy :)

    W wątkach w Rubym najbardziej denerwujące jest to, że operacje blokujące jeden wątek, blokują cały proces. To jedyny duży minus, który napotkałem podczas ich używania. Ten minus neguje największą korzyść z ich używania – np. odpalenie jakiegos wielowątkowego web crawlera jest na wątkach utrudnione – jeden sie przyblokuje i caly proces stoi i czeka na timeout.

    Czy ktoś z czytających pokonał w jakiś elegancki sposób ten problem?

  2. Avatar Drogomir powiedział about 9 hours later:

    Jacek: Też mi się wydaje, że to może być przyczyna.

    Jak można przeczytać tutaj ruby uruchamia GC za każdym razem gdy zaalokuje się 8mb pamięci.

  3. Avatar Moro powiedział 1 day later:

    Odnioslem wrazanie, ze uwazasz green watki za cos zlego? To ze implementacja jest wolna to nie oznacza wcale ze green watki sa gorsze od systemowych, wrecz sa duzo lepsze. Porownaj implementacje green watkow np. w erlangu.

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

    Erlang nie ma współdzielonej pamięci. To są lekkie procesy, a nie wątki.

  5. Avatar JO powiedział 1 day later:

    w Ruby jest gem fastthread ktory daje ci “szybkie natywne wątki” panie Zabiełło

    co do range() to ma pan nawet w tutorialu dla n00bów ze do duzych zbiorów uzywa sie xrange :)

    Pozdrawiam :)

  6. Avatar Jacek Becela powiedział 1 day later:

    Jakub: Czy fassthread rozwiazuje problem blokowania procesu przy zablokowaniu watku?

  7. Avatar Tomash powiedział 1 day later:

    @Jacek: tak. Korzystałeś kiedyś z Capistrano, a jeśli tak to czytałeś jego komunikaty?

  8. Avatar Jacek Becela powiedział 1 day later:

    Korzystam, ale nie wnikam bo mi cholera dziala bezblednie :)

    A wątki ostro męczyłem za czasów 1.8.4 i jestem po tyłach w tym temacie.

    Tym samym statni argument przeciwko Rubiemu w mojej głowie upadł.

  9. Avatar sprae powiedział 2 days later:

    Niedawno Jarosław Zabiełło dokonał testu wydajności różnych interpreterów Pythona i Ruby w natywnych wątkach systemu operacyjnego. Zabrakło mi tam testów IronPythona, który natywne wątki jest w stanie obsłużyć w ramach tradycyjnej biblioteki Pythona. http://sprae.jogger.pl/2008/07/28/python-vs-ironpython-vs-watki/

  10. Avatar Adam Olsen powiedział 2 days later:

    I apologize for commenting in english, but I’ve a few points I believe are important.

    1. The random implementation may be the dominant cost here. Creating a random list before creating the child threads, and having them copy it, should help mitigate it. You could also eliminate the threads and the sorting, just benchmarking the random number generation. 2. In the python versions the main loop is busy-waiting, which could be soaking up a lot of CPU time (although I doubt it matters much here). Use “for t in threads: t.join()” instead. 3. You should try disabling python’s tracing GC (gc.disable()). It behaves quite badly under certain conditions.

  11. Avatar Peter Cooper powiedział 3 days later:

    I’m confused why Ruby 1.8.7 is so slow on this. I get similar numbers to you for the Python version, but my Ruby 1.8.6 (which is little different to 1.8.7) gets 2.85s.

  12. Avatar david koblas powiedział 3 days later:

    Wrote a blog post, but most of the performance difference in this benchmark is because random is a native python library which is slow.

    http://www.skitoy.com/p/python-vs-ruby-performance/172

  13. Avatar Jarosław Zabiełło powiedział 3 days later:

    @Adam Olsen: I have updated the article. I got rid off sorting and list creation. I have only random number generation. But as David Koblas pointed out, it looks like Python has slow random number generator.

    @Peter Cooper: I have no idea why Ruby 1.8.7 is so slow. On my MBP Core2Duo, 2.16 GHz & Mac OS X 10.5.4, Ruby 1.8.7 is even 6x slower than Ruby 1.8.6!

  14. Avatar Marek Kubica powiedział 3 days later:

    Jeszcze wymienie ze Python uzywa juz od dawna watki POSIX:

    http://docs.python.org/lib/module-thread.html

  15. Avatar JO powiedział 3 days later:

    Ps. Ten test polega na samym sortowaniu i roznice / zyski sa na poziomie 10%-14% to oznacza ze pana test panie Zabiełło jest ładnie pisząc do bani, bo implementacja sort może być różna proponuje aby wykorzystał pan jakis text albo strone i ją parsował jakas swoja metoda która jest powtarzalna i katująca mocno dla procesora, wtedy będzie można efekty porownywać.

    Jak u nas ktos na programowaniu rownoleglym przyniosl program ktory po zrownolegleniu mial przyrost szybkosci < 25% to w ogole prowadzacy mowil mu “nara” :)))

    Prosze poprawic test !!!

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

    @Marek Kubica: co z tego, że Python używa wątków skoro GIL nie pozwala im wykorzystać pełni możliwości maszyn wieloprocesorowych/wielordzeniowych?

    @JO: Widzę, żeś nie zauważył, że w update do tekstu zmieniłem kod i już nie ma sortowania. Zostało samo generowanie liczb losowych. Niestety, jak nie urok to sraczka. Okazało się że tym razem Python ma (ponoć) wolny generator liczb losowych. Co nie wybrać, to problem. Panie Oboza, sam sobie napisz dokładne i obiektywne testy jak masz na to czas.

    Z innej beczki. Zapuściłem ostatnio ten mój kod na Solarisie (Sparc, 32GB, 64 rdzeni) Mam tam tylko Javę i JRuby więc ograniczyłem się do tego. Zauważyłem, że JRuby nie wykorzystuje pełnych zasobów maszyny. Java, bez problemu pochłonęła pełne 100% czasu rdzeni.

  17. Avatar wysek powiedział 16 days later:

    “Co nie wybrać, to problem.”

    Ano, nie ma letko;) Testowanie to nie jest taka prosta czynność, że się napisze test i odpali. Trzeba jeszcze czasem trochę pomyśleć ;)

  18. Avatar jc powiedział 17 days later:

    “Jython jest najwyraźniej jeszcze bardzo słabo zoptymalizowany. Pomysły aby na nim odpalać frameworki takie jak Django, to na razie raczej przedwczesny pomysł.” – nie sprawdzałem i nie wiem, jak działa Django na Jythonie, ale wysnuwanie takich wniosków na podstawie mikrotestu generatora liczb losowych jest co najmniej komiczne ;)

    Tak z ciekawości, jakiego algorytmu używa Ruby/JRuby do generowania liczb losowych?

  19. Avatar lopex powiedział 17 days later:

    W tej chwili java.util.Random (MRI używa Mersenne Twister’a który, btw, jest dużo szybszy – shufluje duże słowo co 624 wołań a normalnie robi 4 xory i 4 przesunięcia co powoduje doskonałą utylizację cache’a). W tej chwili JRuby nie używa arity split dla Kernel#rand (a więc jest narzut sprawdzania arności i bardzo duży narzut “boxingu” w tablicę argumentów). W wolnej chwili zakomituję javową wersję MT i dużo szybszy dispatch w Kernel#rand (w zasadzie to on jest wąskim gradłem tutaj a nie generator).

  20. Avatar rmz powiedział 22 days later:

    1. Test jest skopany, generowanie liczb losowych to nie taka prosta sprawa, test może tylko rodzić przypuszczenie że w Pythonie zastosowano lepszy algorytm a w Rubym gorszy do generowania liczb losowych. (Może w Rubym jest skopany?) Element losowy należy w tego rodzaju testach wyeliminować. Zrozumiał bym gdybyś np. testował bazy danych a tylko zestaw danych przykładowych był by generowany.

    2. Od kiedy to “Jython jest kolejnym przykładam całkowitej ignorancji założeń języka Python (o istnieniu jednej, oczywistej drogi do tego samego celu)” myślałem że “istnienie jednej drogi” to filozofia Rubiego a nie Pythona, ale może coś przeoczyłem.

  21. Avatar Jarosław Zabiełło powiedział 22 days later:

    @rmz: Zdecydowanie ci się pomieszało. Jest dokładnie odwrotnie. Istnienie “jednej drogi” to filozofia Pythona, a nie Rubiego. Zobacz PEP20, pkt.13.

  22. Avatar iddqd powiedział 23 days later:

    Spoko blog ale za przeprowadzanie testów to raczej się nie bierz bo wygląda na to, że góry zakładasz wynik i nie znasz wystarczająco bebechów.

    Generator liczb losowych Ruby jest stosunkowo mało losowy( w porównaniu do Pythona) a przez to szybki. Produkcja takich testów i takich http://blog.zabiello.com/articles/2007/04/02/postgresql-vs-mysql-vs-mssql2k obniża wartość bloga.

  23. Avatar lopex powiedział 24 days later:

    @iddqd “Generator liczb losowych Ruby jest stosunkowo mało losowy”. Jak to ? MT to jeden z najlepszych generatorów pseudolosowych jakie istnieją (o ile nie najlepszy w swojej klasie) i przeszedł wszystkie die hard testy i choć nie przydaje się w kryptografi, znakomicie sprawdza się choćby w Monte Carlo.

  24. Avatar jellonek powiedział 24 days later:

    uzywanie jythona 2.2.1 w czasie gdy nie jest od dobrych kilku miesiecy rozwijany jest conajmniej dziwne… trzeba bylo probowac 2.5.1a, choc teraz mozna spokojnie wersji z trunka sprobowac (dopiero “na dniach” wersja 2.5.1 przeszla do trunka z branch/asm). roznica jest ogromna, nawet przy tescie specjalnie przygotowanym by pokazac wyzszosc ruby nad pythonem ;) tak wiec – czekam na aktualizacje, tudziez nowy wpis do bloga ;)

  25. Avatar lopex powiedział 25 days later:

    Lepsza wydajność 2.5.1a to głównie praca nad runtimem. ASM wnosi tylko tyle że po refactoringu i użyciu api ASM kod jest czytelniejszy, wcześniej w źródłach jythona były tragiczne addByte(234), itp.

  26. Avatar rmz powiedział 27 days later:

    1. Siłą Pythona nie jest jego szybkość, jest wręcz wolny, ale ma inne zalety dla których go stosuję, a jak coś ma działać wydajnie to można to dopisać np. w C lub asemblerze 2. Benchmark jest zrobiony beznadziejnie, algorytm generowania liczb losowych w tych językach jest na pewno różny, a który lepszy? nie wiem ale wygląda że w Rubym widocznie jest gorsz bo szybszy 3. Wg mnie jedną zalet Pythona jest to że kod można zapisać w mniejszej ilości niż w innych językach. 10 w Pythonie 100 w Rubym?(Nie znam Rubiego – zgaduję) Za jakiś czas pewnie i tak się okaże że to w jakim język piszemy jest bez znaczenia bo czy napiszemy to w języku A, B, C czy D i tak ostatecznie da się skompilować do tego samego “czegoś” co da nam taki sam efekt końcowy lub dowolnie i automatycznie przetłumaczyć z języka A do B a potem do Y. To tylko kwestia odpowiednich kompilatorów i edytorów ułatwiających pracę. Ale to tylko moje przypuszczenia.

  27. Avatar Jarosław Zabiełło powiedział 28 days later:

    @rmz: Po pierwsze, twój zarzut co do benchmarka jest bez sensu, co do generowania liczb losowych Python używa takiego samego algorytmu, co Ruby (Mersenne Twister). Po drugie, to Ruby pozwala na pisanie krótszego kodu od Pythona, a nie odwrotnie.

  28. Avatar salmon powiedział about 1 month later:

    >Po drugie, to Ruby pozwala na pisanie krótszego kodu od Pythona, a nie odwrotnie.

    Ale nie jest taki czytelny :p

  29. Avatar Jarosław Zabiełło powiedział about 1 month later:

    @salmon: Zależy co. Polemizowałbym. Ruby potrafi być również czytelniejszy od Pythona.

  30. Avatar salmon powiedział about 1 month later:

    Możliwe, ale ten Twój przykład z wątkami jest dla mnie mało czytelny, a w przypadku Pythona potrafiłem zrozumieć działanie programu, nie znając jeszcze tego języka :)

  31. Avatar Jarosław Zabiełło powiedział about 1 month later:

    Przykład z wątkami raczej nie nadaje się na pierwszy rzut dla kogoś kto nie zna języka. Ruby jest bardziej skomplikowanym językiem od Pythona, wiadomo. Ale jak już się go opanuje to Ruby potrafi być bardziej zwarty i piękniejszy od Pythona.

  32. Avatar Hawkerb powiedział 2 months later:

    Ten caly test to jakas kpina i przejaw ignorancji. Jakim cudem niby ten test ma mówić o prędkości wątków w rubym 1.8 i 1.9 skoro OBIE implementacje mają global interpreter lock, czyli nigdy dwa wątki nie są uruchomione jednocześnie (nawet na 2,4 czy 16 rdzeniach)?! Zresztą, przecież to WIDAC w wynikach – czas ruby1.9 jest prawie identyczny dla 1 watku i 20.

    O tym, ze dane autor uzywa puts w benchmarku, mierzy czas za pomoca Time.now i stosuje random w glownej petli, nie bede pisal, bo nie ma po co.

    Jednym zdaniem, jesli chodzi o porownywanie wydajnosci implementacji rubiego, to ten artykul nie ma zadnej wartosci (a co do innych jezykow, to szkoda mi czasu analize).

  33. Avatar Jarosław Zabiełło powiedział 2 months later:

    @Hawkerb: Ruby 1.9 potrafi już wykorzystywać natywne wątki systemu operacyjnego.

(leave url/email »)

   Pomoc języka formatowania Obejrzyj komentarz