Ruby - wydajność/benchmarki

Witam

Chciałbym się dowiedzieć jak to jest z wydajnością rubiego - dochodzą mnie sprzeczne głosy z jednej strony słyszę że np. twitter jest na railsach a z drugiej inni specjaliści mówią że railsy są wolne bo działają via interpretator
Czy są jakieś konkretne badania przy dużych obciążeniach które by potwierdzały albo negowały powyższe uwagi? i jakie jest wasze zdanie z perspektywy pracy na railsach na temat jego szybkości i wydajności dla dużych projektów

Ruby jest szybki dość, jak potrzebujesz super wydajności to stawiasz proejkt na sinatrze-synchrony albo Goliath. masz wtedy ~3000req/sec obsluzonych. W rails pojedyncze zapytania zajuje okolo 40-50ms dokłądnie nie wiem, więc spoko wolnej ale nadal dość szybko. Coś za coś.

Na pewno wystarczająco szybko, bo wątpie byś miał ruch jak facebook.

Na tej stronie masz benchmarki odnośnie różnych języków programowania wraz z możliwością ich porównywania (np. java i ruby)
http://shootout.alioth.debian.org/

Nie weryfikowałem nigdy poprawności zamieszczanych tam wyników, ani nie porównywałem ich wyników ze swoimi, więc nie wiem na ile jest to wiarygodne źródło.
Odnośnie Twojego pytania imho lepiej jest je zadać jako: czy ruby jest wystarczająco wydajny do pracy nad X.

Ale co, “hello world”? Daj spokój. Szkoda o tym wspominać bo raczej osoba pytająca ma na myśli “normalną” appkę.

[quote=gotar]W rails pojedyncze zapytania zajuje okolo 40-50ms dokłądnie nie wiem, więc spoko wolnej ale nadal dość szybko. Coś za coś.

Na pewno wystarczająco szybko, bo wątpie byś miał ruch jak facebook.[/quote]
Ja powiem tak: pod względem wydajności railsowa appka nie będzie się różnić od appki w php postawionej na podobnym frameworku (np. Symfony).

No wszelakie benchmarki mają jak zawsze niebyt wielki sens. Jak pisałem nie sądzę byś miał taki projekt w którym dobrze napisana aplikacja w rails będzie stanowiła bottleneck ze względu na rails

Albo napisać w czymkolwiek drugą aplikację do dokonywania ciężkich obliczeń i komunikować się z nią przez wewnętrzne API.

A benchmarki kłamią. Chyba, że sam je robisz na własnej aplikacji.

Dużo zależy od tego jaki jest profil aplikacji - jeśli jest to typowa appka, która głównie służy do wyświetlania danych z bazy, dodawania ich do bazy, to narzut na komunikację z DB jest istotnie większy w porównaniu z samym kodem wykonywanym po stronie Rubiego (czy innego języka). Natomiast jeśli istotna funkcjonalność typowego zapytania zakłada duże ilości obliczeń (powiedzmy szukanie połączeń lotniczych), to wydajność Rubiego może być ograniczeniem. Jeśli przewidujesz taki scenariusz polecam użycie JRubiego - wtedy wąskie gardła można łatwo przepisać na Javę/Scalę. Większość aplikacji i tak pozostanie w Rubim, ale będzie ona działać zdecydowanie szybciej.

Jak przykład mogę podać implementację obliczania długości Levenshteina w JRubim i Javie:
Kod:

user system total real
ruby 0.230000 0.000000 0.230000 ( 0.230000)
ruby 0.236000 0.000000 0.236000 ( 0.236000)
ruby 0.233000 0.000000 0.233000 ( 0.233000)
ruby 0.229000 0.000000 0.229000 ( 0.229000)
ruby 0.233000 0.000000 0.233000 ( 0.233000)
ruby 0.233000 0.000000 0.233000 ( 0.233000)
ruby 0.231000 0.000000 0.231000 ( 0.231000)
ruby 0.232000 0.000000 0.232000 ( 0.232000)
ruby 0.233000 0.000000 0.233000 ( 0.232000)
ruby 0.233000 0.000000 0.233000 ( 0.233000)
java 0.014000 0.000000 0.014000 ( 0.014000)
java 0.014000 0.000000 0.014000 ( 0.014000)
java 0.018000 0.000000 0.018000 ( 0.018000)
java 0.024000 0.000000 0.024000 ( 0.024000)
java 0.015000 0.000000 0.015000 ( 0.014000)
java 0.018000 0.000000 0.018000 ( 0.018000)
java 0.014000 0.000000 0.014000 ( 0.014000)
java 0.014000 0.000000 0.014000 ( 0.014000)
java 0.014000 0.000000 0.014000 ( 0.014000)
java 0.014000 0.000000 0.014000 ( 0.014000)

Coś się kopci - czy wy również widzicie dwie wiadomości?

Tak, jedno nie wyklucza drugiego.

To są moje benchmarki, napisane właśnie pod kątem konkretnego zastosowania. I ta różnica jest dla mnie akurat bardzo istotna.

To właśnie spoko. Odnosiłem się do benchmarków, które „ktoś kiedyś zrobił i wyszło, że PHP jest szybsze”. Sprawdzanie swojej aplikacji ma duży sens, czytanie cudzych już niespecjalnie.

W ramach zabawy podczas nauki pętli i iteratorów porównałem ich szybkość za pomocą takiego programu:

x = 0
start = Time.now
while x < 100_000_000
  x += 1
end
puts "Czas: #{Time.now - start} sekund."

x = 0
start = Time.now
100_000_000.times do
  x += 1
end
puts "Czas: #{Time.now - start} sekund."

x = 0
start = Time.now
1.upto(100_000_000) {x += 1}
puts "Czas: #{Time.now - start} sekund."

Zaokrąglone wyniki (wielokrotnie powtarzane) dla tych trzech przypadków to odpowiednio:
3,8 s
11,1 s
11,3 s
Czy to normalne, że iteratory są wolniejsze od pętli “while”?

x.times i 1.upto(x) tworzą obiekty klasy Enumerator. while sth do omija to i, jak podejrzewam (nie sprawdzałem dokładnie kodu Rubiego) jest zaimplementowane bezpośrednio w C, stąd różnica czasowa.

PROTIP: http://www.ruby-doc.org/stdlib-2.1.2/libdoc/benchmark/rdoc/Benchmark.html

Obu kolegom dziękuję za odpowiedź. @Arnvald - wszystko jasne, jeżeli to z powodu C, to wyjaśnia sprawę. @sharnik - za pomocą Benchmark.measure otrzymałem mniej więcej podobne wyniki.
A tak przy okazji, zauważyłem że te same testy wydajności (a właściwie nie same wyniki, lecz względne porównanie wyników) wypadają różnie, w zależności od systemu operacyjnego. Ja “jadę” na 32-bitowej Viście (posługuję się wyłącznie Windowsami).

Tu masz porównanie szybkości różnych interpretacji Ruby. Zdecydowanie najszybsze są rozwiązania używające JRuby. http://www.madebymarket.com/blog/dev/ruby-web-benchmark-report.html?utm_source=rubyweekly&utm_medium=email Twitter, to projekt, której specyfika (distributed, fault tolerant, high volume) idealnie nadaje się do Erlanga a nie na żadne Railsy. Facebook odrobił już tą lekcję, i ich aplikacja chatowa używa Erlanga.

Dzięki za linka do testów szybkości. Co do Erlanga i nie-RoR, czy to oznacza, że do tworzenia różnych stron/aplikacji webowych używa się różnych języków/frameworków, tych, które w danym przypadku lepiej spełnią swoje zadanie?

Twitter to nie jest typowa aplikacja webowa. To bardziej rozproszony komunikator o wielkiej skali rozproszenia co idealnie nadaje się dla Open Telecom Platform Erlanga. Po prostu, jego twórcy zaczęli pewnie tworzyć Twittera jako zwykły startup , trochę zabrakło im wyobraźni co do natury projektu jaki tworzą (a może też i wiedzy, że do takich aplikacji lepiej użyć innego narzędzia).

To ciekawe, co piszesz o Twitterze. Dzięki za wytłumaczenie.

Z tego co pamiętam to właśnie z powodu niskiej wydajności przy tak ogromnej ilości tweetów na sekundę twitter odszedł od ruby na rzecz scali jeżeli chodzi o logikę aplikacji i ruby pozostał tylko jako warstwa prezentacji. Ale faktem pozostaje to, że większość stron może tylko pomarzyć o takim ruchu jaki generował twitter kiedy zaczęły się problemy. Tak więc nie sądzę, że to jest brak wyobraźni, tylko co najwyżej umiejętność dostosowania się do tego co w danej chwili się dzieje.

Nie znam co prawda Erlanga, ale gdyby był jakiś framework erlangowski w którym tak łatwo stworzyć startup jak w railsach, to pewnie o wiele więcej było by startupów pisanych w Erlangu.

1 Like

Tu nie chodzi tylko o ruch, ale o naturę tego ruchu. Tweety to nie są typowe requesty HTTP. Tweety to komunikaty UDP. Tysiące milionów takich wiadomości. Do takiego projektu nadają się rozwiązania stosowane w telekomunikacji. Erlang “z palcem w organizmie” uniósłby ruch Twittera.