Nowe wyniki prezentują się tak [wyniki dla procesora Intel Core 2 Duo T6600 2.20 GHz [2 rdzenie 64 bitowe pod 64 bitowym Windows 7]:
C# z .NET 4.0 - 1.17 ms
Java 1.5 z przełącznikiem -server - 1.096 ms
Java 1.6 z przełącznikiem -server - 2.8895 ms
Python 2.6 - 10.88 ms
Z radością jednak odnotowuję, że słuszne były moje przewidywania i słuszne zdziwienie słabym wynikiem C# :-) szkoda tylko, że wszystkiemu winien był taki błąd :-)
[update: 23/10/2009 - dodałem informacje o wynikach programu w C i parę uwag]
Tak nie miałem pomysłu na to co dziś napisać ;-) więc zrobiłem sobie szybki test co jest szybsze [w obliczeniach] Java, Python czy C#, kontrolnie postanowiłem dodać też C :-).
Przyznam, że z języków wykonywanych w wirtualnych maszynach stawiałem na C#.
W każdym z języków napisałem program, którego celem było policzenie numerycznie 1000 razy całki oznaczonej w przedziale od -10 do 10 [niedomkniętym z prawej] w 10000 krokach z funkcji:
Wynikiem jest coś bliskiego pierwiastkowi z liczby pi [swoją drogą to była rzecz na analizie matematycznej która mnie zachwyciła, całka z funkcji w której użyta jest e, a wynikiem jest pierwiastek z pi, czyli istnieje związek między niektórymi stałymi matematycznymi... może to zrobiło na mnie takie wrażenie bo byłem wtedy świeżo po czytaniu Kontaktu Carla Sagana? :-)].
No i wyniki wyglądają tak [wszystkie czasy dla pojedynczego policzenia całki]:
|
Przyznam, że byłem zaskoczony. Przed uruchomieniem testów dałbym sobie rękę obciąć za to, że z języków wykonywanych przez maszyny wirtulane wygra C#, bo coś mi się po głowie kołatało, że .NET swobodnie korzysta z koprocesora [kto jeszcze pamięta co to jest? ;-) ja pamiętam, że moją przygodę z PC zaczynałem na komputerze bez koprocesora i że były nawet softwareowe emulatory tegoż :-)], czego Java nie może robić bo jej matematyka zmiennoprzecinkowa nie jest do końca zgodna z tą stosowaną w x86 [dla pewności w przypadku Java'y uruchomiłem jeszcze test z arytmetyką zgodną ze strictfp, i wtedy czas jednej iteracji to 20 ms dla Turiona 64].
A tu proszę, Java okazała się w tym przypadku 2.5-3 raza szybsza od C# :-) i 2.85 do 3.33 razy szybsza od Pythona [testy z Pythonem 3000, czy może 3.1? pokazują, że Python troszkę przyśpieszył].
Do testów użyłem Sun Java 1.6.0_15 [czyli chyba najnowszej], dla Pythona był to ActiveState Python 2.5 i oryginalny Python 2.5 z Python.org, w przypadku .NET użyłem wersji 3.5 z włączoną optymalizacją.
Programy wyglądały tak [umieszczam tylko funkcje obliczające całkę, N=10000, kody źródłowe i wersje skompilowane znajdziecie w archiwum, chętnie poznam Wasze wyniki :-)].
Java:
static double calc() {
double sum = 0;
for (int i=0; i<N; i++) {
double x = 20.0*i/N-10.0;
sum+=Math.pow(Math.E, -x*x)*(20.0/N);
}
return sum;
}
C#:
static double calc() {
double sum = 0;
for (int i = 0; i < N; i++) {
double x = 20.0f * i / N - 10.0f;
sum += Math.Pow(Math.E, -x * x) * (20.0 / N);
}
return sum;
}
Python:
def calc():
sum=0
for i in range(0,N):
x=20.0*i/N-10
sum=sum+math.e**(-x**2)*(20.0/N)
return sum
C:
double calc() {
int i;
double sum = 0;
for(i=0; i<N; i++) {
double x = 20.0*i/N-10.0;
sum+=pow(M_E, -x*x)*(20.0/N);
}
return sum;
}
Przyznam, że jestem pozytywnie zaskoczony wynikiem Java'y :-)
Jest co prawda wolniejsza od C, ale "tylko" o 2.5 raza, w przypadku C vs. C# mamy różnicę prawie 1 rzędu w wydajności, a to już coś.
Wszystkie testy odbywały się na moim laptopie, z procesorem Turion 64ML-30 1.6 GHz ściętym do 800 MHz.
Jak komuś się będzie chciało to prosiłbym o Wasze wyniki :-)
* Turion 64ML-30 o nominalnym taktowaniu do 1.6 GHz, ale softwareowo "obcięty" do 800 Mhz
** ActivePython wydaje się być wolniejszy od "oryginalnego" Pythona.
Podobne postybeta
Raspberry Pi to nie jest demon prędkości ;-)
Całkujący Dart ;-)
Plus dla Scala, minus dla Groovy ;-)
A JavaScript i tak szybszy ;-)
Język Go dla Windows :-)
Uruchomiłem moje testy na moim firmowym laptopie [Intel Core Duo 2.16 GHz] i wyniki są jeszcze ciekawesze :-)
OdpowiedzUsuńJava - 10 ms
Python - 27 ms
C# - 32 ms
Java 1.6.0_16, .NET 3.5 i róźnica jest chyba w Pythonie, bo to nie ActiveState a to co można ściągnąć ze strony pythona.
Dla porównania na firmowym laptopie, kod w C potrzebuje 4 ms na obliczenie całki :-) Czyli Java nie jest taka wolna :-)
OdpowiedzUsuńMysle ze dla calosci formy warto by bylo przetestowac tez szbkosc C.
OdpowiedzUsuńZrobiłem to ;-) o czym piszę wyżej ;-)
OdpowiedzUsuńC - 4 ms
Java - 10 ms
Python - 27 ms
C# - 32 ms
Na Core Duo 2.16 GHz
Mała podpowiedź. JVM jeżeli widzi taką pętle to szybciutko kompiluje sobie bytecode do kodu natywnego. Dla mojego testu w pierwszych 10 obrotach czasy wykonania calc() wynosiły:
OdpowiedzUsuń32,26,9,9,9,8,8,9,8,9
W ostatnich 10:
4,4,5,4,4,5,4,4,5
A zatem tyle ile w C. Ameryki tutaj raczej nie odkrywam, ale od kilku lat JVM z tym małymmykiem kompilacji do kodu natywnego w locie dla często wykorzystywanych fragmentów jest chyba najfajniejszym środowiskiem do pisania kodu wydajnego i jednocześnie eleganciego oraz łatwego w utrzymani nawet przez mniej doświadczonego programistę.
@koziołek wiem :-) dlatego właśnie całka była liczona 1000 razy, po to by wynik się ustabilizował. Było to krzywdzące dla C, który praktycznie od początku jest w stanie "polecieć" pełną prędkością, a faworyzowało Java i C# [Pythona nie, bo Python sam się przyznaje, że w jego przypadku optymalizacja to proste wyrżnięcie __doc__], które mogą dokonać kompilacji w locie, a nawet optymalizacji kodu przez obserwowanie co robi pętla. Ale ciekawe było popatrzeć jak wyglądają różnice w wynikach, mnie zaskoczył .NET, bo choć go nie lubię to wydawało mi się, że powinien mieć wyniki podobne do Java'y.
OdpowiedzUsuńW kodzie pythonowym masz obliczanie kwadratu przez x**2, za to w innych źródłach x*x. U mnie wersja z x**2 wykonuje się w 18-18.5ms, za to wersja z x*x w 15.5-16ms. Uruchamiałem na Pythonie 2.6.2 dla win32, z python.org. Trochę się dziwię, że python sam tego nie zauważa i najprawdopodobniej liczy to przez pow(x, 2.) co jest dosyć wolne - może nie mam włączonej jakiejś optymalizacji?
OdpowiedzUsuńTrochę się zdziwiłem, że jak zmieniłem range na xrange to czas był taki sam (w granicy błędu).
Szczerze mówiąc właśnie wynik Pythona najbardziej mnie zaskoczył (pozytywnie). Tam nawet wykonanie pustych pętli zajmuje wieki - szkoda, bo ze wszystkich tych języków ten jest moim ulubionym. Ale w końcu python nie jest od obliczeń numerycznych - można, ale prędzej przez numpy.
Javą bardzo pozytywnie zaskoczyłem się już nie raz - mam porównanie, bo piszę sporo ciężkich obliczeniowo rzeczy w C i podobne rzeczy w Javie. Chociaż samego języka nie lubię to jestem przekonany, że jego powolność to głównie nieprzyjemne wrażenie pozostałe w głowach użytkowników z czasów kiedy była naprawdę wolna i jak w 1999 roku na Pentiumie z 64MB ramu wchodziło się na stronę z appletem javy to lampka od dysku zaczynała migać jak do disco, wszystkie procesy się zamrażały i spokojnie można było iść na kawę...
Zrobiłem małe porównanie na moim sprzęcie, pod systemem Linux
OdpowiedzUsuńMaszynka służy wyłącznie jako przeglądarka, więc procesor stłumiony jeszcze bardziej niż Twój.
$ cat /proc/cpuinfo
model name : Intel(R) Pentium(R) M processor 1500MHz
cpu MHz : 598.498
cache size : 1024 KB
Podaję wyniki z polecenia time, które jest nieco bardziej wiarygodne.
Ze względu na system podarowałem sobie .net ale porównanie C i Java mówi samo za siebie.
time speed
7,96s user 0,04s system 95% cpu 8,350 total
time java -server Speed
11,80s user 0,13s system 91% cpu 13,041 total
time python speed.py
58,66s user 0,48s system 87% cpu 1:07,68 total
@blog dlaczego uważasz, że time jest bardziej wiarygodne? Przecież ono mierzy czas działania programu, a nie to było istotą pomiarów.
OdpowiedzUsuńWiadomo, że uruchomienie programu zabiera czas, ale w przypadku złożonych problemów obliczeniowych ten czas jest pomijalny.
a ja pokusiłem się o zrobienie części testów na moim nowym laptopie ;-)
I tak jedna iteracja zajęła:
C 32bit [kompilator z Dev-Cpp] - 0.168 ms
C 64bit [lcc-win32 64bit] - 0.68 ms
Java 32bit - 4.7 ms
Java 64bit - 3.8 ms
.NET 64bit - 14 ms
Python 2.5.2 32bit - 10.3 ms
Python 2.5.4 64bit - 10.16
Aż świerzbi mnie napisanie tego w php, by pokazać dzieciom neo co jest wydajniejsze :D
OdpowiedzUsuńHm... Scala/Ruby(JRuby)/Groovy no i jeszcze jak wygląda sprawa z Jthonem. Wiele tzw. postmodernistycznych języków programowania można ruszyć na JVM nie. Ciekawe mogą być różnice na poziomie samej maszyny.
@RMK
OdpowiedzUsuńpolecenie time jest bardziej wiarygodne, ponieważ współczesne systemy są wielozadaniowe i czas procesora jest dzielony z innymi programami, które mogą "niespodziewanie" zacząć pożerać zasoby, fałszując w ten sposób wyniki. Oto przykład:
speed 7,28s user 0,06s system 57% cpu 12,847 total
speed 7,24s user 0,03s system 96% cpu 7,512 total
w pierwszym przypadku miałem uruchomione dwa procesy.
Oczywiście taki sposób pomiaru jest krzywdzący dla języków mających duży narzut przy starcie, ale przy większej ilości iteracji ta różnica będzie się coraz bardziej zacierała, podczas gdy błędy wynikające z "szumów tła" nasilały by się coraz bardziej.
@koziołek,
co do wyników PHP to chyba nie ma wątpliwości, skoro kompilacja na JVM oznacza zazwyczaj 6x przyśpieszenie.
Nie wiem jak z Jthonem, ale JRuby jest wyraźnie szybszy niż CRuby 1.8. Nie porównywałem z Ruby 1.9 - tu różnica będzie mniejsza.
@koziołek natchnąłeś mnie ;-) wcześniej myślałem o użyciu JavaScript'u ale wydawało mi się to głupim pomysłem, bo przecież wolny jest........
OdpowiedzUsuńI takie mam wyniki [na mojej firmowej maszynie]:
cscript [część Windows Scripting Host] - między 41 a 52 ms
Firefox 3.5.3 - 3.782 ms
Chrome 4.0.223.11 - 7.591 ms
IE8 się poddał
Opera 10.00 - 22-23 ms
WTF? JavaScript w FF szybszy czy porównywalny do C?
Dodając do tego JavaScriptowego testu, tutaj kod:
OdpowiedzUsuńN=10000;
M=1000;
function calc() {
var sum = 0;
var i;
for (i=0; i<N; i++) {
var x = 20.0*i/N-10.0;
sum+=Math.pow(Math.E, -x*x)*(20.0/N);
}
return sum;
}
var start = new Date().getTime() ;
var i;
var sum=0;
for (i=0; i<M; i++) {
sum+=calc();
}
var end = new Date().getTime();
var time = end - start;
document.write((time*1.0/M)+"
");
Wyniki są bardzo niestabilne, bo mogą się różnić nawet o 30-40%
Gdy chcecie spróbować w WSH, to document.write zmieńcie na WScript.Echo i nagrajcie plik jako speed.js
Są niestabilne, bo zapewne przeglądarka ciągnie też inne duperele np. pluginy, które korzystają z JS. Samo przetwarzanie JS jest jednowątkowe więc każda duperela otwarta w tle będzie zaburzać pracę.
OdpowiedzUsuń@blog po to odpalałem te programy testowe po kilka razy. Przełączenie między wątkami i procesami kosztuje, ale mniej niż np. uruchomienie JVM.
OdpowiedzUsuń@RMK
OdpowiedzUsuńNie do końca. Czas startu JVM przy 1000 iteracjach jest mniejszy od błędów pomiaru wynikających z tego że mierzysz czas rzeczywisty zamiast czasu procesora.
Zobacz zresztą jeszcze raz wyniki:
$ time java -server Speed
12
java -server Speed 11,82s user 0,09s system 95% cpu 12,487 total
Pierwszą liczbę wydrukował Twój program, resztę wypisał "time".
Te liczby są baaaardzo podobne, z tym że proces wykorzystał "tylko" 95% czasu procesora - więc pomiar czasu rzeczywistego jest obarczony 5% błędem.
Taka ciekawostka,
pobawiłem się Waszym przykładem w JavaScript i tu wyniki są jeszcze ciekawsze. Widać jak długą drogę przebył ten język od swych narodzin :)
Spidermonkey (silnik ze starego firefox'a)
$ time js speed.js
178.142
js speed.js 174,36s user 0,87s system 98% cpu 2:58,80 total
Rhino (implementacja java)
$ time rhino speed.js
55.721
rhino speed.js 53,82s user 0,50s system 95% cpu 56,905 total
Google V8 (wersja z przed pół roku)
time ~/app/js-v8 speed.js
16.732
~/app/js-v8 speed.js 16,47s user 0,10s system 97% cpu 16,971 total
Niestety nie mam najnowszego silnika, który siedzi w Fx3.5 a który ma własny JIT - jego wyniki powinny znajdować się gdzieś pomiędzy Rhino a V8.
@blog U mnie okazuje się, że V8 jest wolniejszy od FF3.5.2 :-) ale możliwe, że to nie wina samego silnika, ale tego, że jest osadzony w przeglądarce, i czas zabierać może przeglądarka.
OdpowiedzUsuńZ tego co widzę na WinXP przy użyciu timeit [z Windows Resource Kit, który podobno jest odpowiednikiem time] to procesy "testowe" używają procesora w 96.5%, a uruchomienie JVM potrafi zająć nawet 4 sekundy ;-) czyli żeby porównywać czas ładowania JVM i przełączania wątków to programy dla JVM powinny działać ponad 114 sekund. Tak btw. w ciągu przeciętnie tych 11 sekund moja Winda przerzuca kontekst ponad 100 razy ;-) czyli ponad 10 tysięcy razy na sekundę.
@GMK,
OdpowiedzUsuńco do porównania z Fx3.5 to spróbuję później jeszcze coś wykombinować. Zazwyczaj v8 jest szybsze, ale w tym przypadku może być inaczej - wszystkie te nowe maszyny wirtualne są dość trudne do przewidzenia, co chwilę dodają kolejne optymalizacje kodu.
Jeśli chodzi o naszą dyskusję na temat polecenia time, to wychodzą tu różnice pomiędzy używanymi przez nas systemami:
U mnie start JVM to 0,2 - 0,4s
natomiast różnice wynikające z "szumów tła" to 1,2s
Tu masz przykład Twojego programu dla N=0
$ time java -server Speed
0
java -server Speed 0,19s user 0,04s system 67% cpu 0,339 total
Zgaduję że większość czasu pożerają operacje dyskowe.
Przyszła mi do głowy jeszcze jedna rzecz... Zgaduję że robiąc kilka testów odrzucasz te z "nieprawidłowymi" wynikami? Jeśli tak to faworyzujesz programy z krótkim czasem wykonywania.
Wyobraź sobie co będzie jeśli np Twój zegarek co 30s rysuje wskazówki zabierając 100% czasu procesora na 1s. Na monitorze systemowym niewiele będzie widać, bo ten uśrednia wyniki - będziesz tylko widział 3% obciążenie systemu.
Krótki program będzie miał szczęście, ale jeśli coś działa minutę, albo dwie?
@blog Uruchamianie JVM jest tricy ;-) może zająć do 4 sekund, szczególnie gdy uruchamia się po raz pierwszy, a w innym momencie może pójść jak burza. Przed chwilą zrobiłem testy i teraz przy pierwszym uruchomieniu potrzebowała 400-500 ms, a w kolejnych już tylko 120-160 ms.
OdpowiedzUsuńChodzi też o to, że niedokładność pomiaru wynikła z "szumów" jest zazwyczaj podobna dla wszystkich pomiarów, czyli błąd względny jest prawie zawsze taki sam [i dla Windows wynosi około 3.5%], fakt że jak coś się wykonuje 10 ms to ten błąd może wynieść 0.35 ms, a jak coś się wykonuje 100 ms to wyniesie 3.5 ms, ale porównanie rzędów wielkości jest nadal uzasadnione, bo 10 ms +/i 0.35 ms jest 10 razy mniejsze niż 100 ms +/- 3.5 ms.
Doliczanie czasu potrzebnego na uruchomienie faworyzuje C i w przypadku Windows prawdopodobnie również .NET, a "krzywdzi" Java'ę i Pythona.
A jako fizyk z wykształcenia nie mogę sobie pozwolić na nieścisłości w "procedurze" badawczej ;-)
Każdy program jest uruchamiany 3 razy [czasem więcej] i jako wynik podawana jest średnia z tych uruchomień, wszystkie wyniki które odstają zbytnio od normy są odrzucane, odstawanie od normy znaczy co najmniej 30-40% odchyłkę, bo widać wyraźnie, że w tym czasie komputer miał ciekawsze rzeczy do robienia.
Jest tu milczące założenie, że komputer w trakcie wszystkich uruchomień jest podobnie obciążony, co można uznać za uzasadnione przypuszczenie z racji tego, że w momencie testów robię testy dla jednego języka, później dla drugiego, trzeciego i tak dalej, a następnie odpalam znów dla wszystkich języków i sprawdzam ich wyniki [praktycznie zawsze są porównywalne z tymi wcześniejszymi].
OK, tu testy w których wszystko wykonywało się 30 sekund :-) [wyniki są uśrednione z 3 pomiarów]
Java - 10.25 ms
C# - 34.14 ms
Python - 29.19 ms
C - 4.25 ms
Żeby nie liczyć zbytnio czasów potrzebnych na odwołanie się do systemu w celu ustalenia czasu, działa to tak, że jest 100 iteracji, pobranie czas i sprawdzenie czy już kończyć, później czas jest dzielony przez liczbę wykonań funkcji calc().
Hej,
OdpowiedzUsuńMożna by się pokusić o odpalenie testu dla Pythona z JITem, dla wyrówniania szans - CPython domyślnie nie używa JITa. Wystarczy zainstalować psyco umieścić na początku skryptu:
import psyco
psyco.full()
Coś jest na rzeczy :-)
OdpowiedzUsuńZ psyco i kompilacją JIT 5.83 ms, bez 13.68 ms na moim Core 2 Duo 2.2 GHz [czy jakoś tak]. Jest poprawa :-)
Dla porównania Java 64 bit potrzebuje 4.43 ms na 1 iterację.
Hmmm... bardzo ciekawe
OdpowiedzUsuńMoje wyniki .Net 4.0 vs Java 1.6.0_07 na Core-i7:
http://img515.imageshack.us/img515/9586/bnc3.png
Jak widac, DIAMETRALNIE rozne.
Inny prosty test:
http://img42.imageshack.us/img42/6766/bnccs.jpg
http://img683.imageshack.us/img683/5762/bncjv.jpg
Tutaj Java 17(sic!) razy wolniejsza od c#4.0
Skad te wyniki? Przyznaje, ze srednio znam sie na Javie, wiec moze robie cos nie tak?
@KomarWodny: Możesz zapodać źródła z tego drugiego testu, bo literki ciut małe i nie umiem doczytać.
OdpowiedzUsuńA wyniki pierwszego testu już rozumiem. Walnąłem babola w kodzie dla C# i nikt go nie zauważył [chociaż rozumiem dlaczego, bo nie widać go w treści postu a nikt niestety nie pociągnął całych źródeł], w C# używałem DateTime.Now.Ticks zakładając, że zwraca ono nanosekundy, a zwraca 1/10 nanosekudny, czyli z grubsza można by próbować dzielić wyniki wyżej przez 10 by uzyskać prawidłowe wartości, wtedy wg. powyższych wyników Java byłaby 3 razy wolniejsza.
Chociaż w rzeczywistości jest podobnie wydajna, tutaj wyniki dla Java'y
http://myscreen.przemelek.pl/img?id=agpzY3JlZW4ybmV0chELEgpTY3JlZW5TaG90GM5lDA
A tu dla C#:
http://myscreen.przemelek.pl/img?id=agpzY3JlZW4ybmV0chELEgpTY3JlZW5TaG90GLZtDA
już po usunięciu błędu.
Będę musiał zmienić treść posta żeby odpowiadał rzeczywistości. Dzięki za sprawdzenie.
Ja dodam od siebie (mimo, ze to dawno było), ze metoda testowa jest conajmniej zła. Żeby zbadać prawidłowo czas wykonania aplikacji (nie używaj w C# trybu deubga - skompiluj i uruchom z linii poleceń będzie działał szybciej) to jeszcze wypadałoby zadbać o to, żeby takie same i taka sama ilość procesów była uruchomiona. C# testujesz kiedy masz włączone JVM a JVM zżera więcej zasobów niż .NET framework (widać na screenach). Taka różnica przy tak niewielkich różnicach czasowych może naprawdę kolosalną róznicę zrobić
OdpowiedzUsuńA gdy testuje JVM mam włączonego .NETa. Testowałem to też poza środowiskami i wyniki są porównywalne. Jeśli twierdzisz inaczej, to proszę o dowody, chętnie je przejrzę.
OdpowiedzUsuńBtw. jak na screenach widać, że JVM zżera więcej zasobów niż .NET? Chodzi o to, że więcej okien jest otwarte?
Porównywalne wyniki były gdy odpalałem JVM i .NETa jako "jedyne" procesy [poza systemowymi i explorerem].
Ta. Teraz zauważyłem (to ten sam Anonimowy co wczoraj) niestety ale bezedurny sposób zliczenia.
OdpowiedzUsuń1. System.currentTimeMillis() - zwraca w milisekundach, więc ta sama jednostka powinna być użyta przy .NET ....
2. Obliczenie milisekund w .NET milisekund tak
Console.WriteLine(time / 1000 / M);
jest conajmniej dziwne....
3. Do obliczenia powinna być użyta ta konstrukcja
Console.WriteLine(time / TimeSpan.TicksPerMillisecond / M);
co da nam rzeczywiste wyniki.
Z moich testów po poprawieniu wynika, że .NET jest 4 razy szybszy niż Java...
Porównanie wychodzi
1125 dla .NET i 4641 dla Javy. Pythona nie instalowałem bo nie mam takie potrzeby. Dla ciekawości wrzucę aplikację w nocy na jakiś mocny serwer i zobaczymy ile tam będzie działać.
z ciekawości zrobiłem to samo w PHP
OdpowiedzUsuńWynik u mnie: 7.093357
@jmail:
OdpowiedzUsuń1) jest opisane, że w pierwszej wersji błędnie założyłem, że funkcja .NETowa zwraca nanosekundy, dlatego wyniki dla .NET zostały poprawione [czyli czas został zmniejszony o 10, co zresztą pokazały testy już z poprawionym obliczaniem]. Dodatkowo to czy mierzy się nanosekundy, milisekundy czy nawet godziny nie ma znaczenia w momencie gdy zapewni się odpowiedni interwał na pomiar. W przypadku milisekund i nanosekund gdy na cały test potrzeba 2 sekund, a w tym trakcie wykonuje się 10 mln operacji [gdy jako operację traktujemy pojedynczą iterację pętli] to zmiana jednostki pomiarowej wprowadza w najgorszym przypadku [czyli takim gdy coś trwało nie 2000 milisekund, a 1999.001 milisekundy [a zostało policzone jako 2000] różnicę wyniku na poziomie 0.5 promila, to było wałkowane wyżej w komentarzach gdy była mowa o JavaScripcie. To potwierdzają też testy przeprowadzone z użyciem System.nanoTime(). Z tego co pamiętam kod testów nie był zmieniany żeby była dokumentacja wcześniejszego błędu o którym przeczytać możesz u góry postu.
2) masz info o błędzie, fakt jest to dziwne bo błędne
3) była, o czym masz w updacie o której mowa w wyższych punktach.
4) zrób test dla Java'y z przełącznikiem -server, wtedy dostaniesz takie wyniki jak moje. O czym też masz w opisie.
Szczerze to nadal dziwią mnie wyniki Java'y zważywszy, że nie może ona używać do obliczeń kooprocesora [w pełni], a C# może. W przypadku .NET/C# jest też przyrost prędkości w .NET 4.0. W Java'ie prędkość spada po przejściu z 1.5 na 1.6 ;-)
Ciekawy wynik dla PHP.
@jmail: jeszcze jedno, jak możesz podziel się źródłem w PHP i swoimi wersjami dla C# i Java'y. Bo ewidentnie widzę, ze trzeba będzie jeszcze raz to opisać [bo nie wszyscy czytają update].
OdpowiedzUsuńTen komentarz został usunięty przez autora.
OdpowiedzUsuńKod PHP:
OdpowiedzUsuń$N = 10000;
$M = 1000;
$E = 2.71828182845904523536;
function calc() {
global $N;
global $E;
$sum = 0;
for ($i=0; $i<$N; $i++) {
$x = 20.0*$i/$N-10.0;
$sum+=pow($E, -$x*$x)*(20.0/$N);
}
return $sum;
}
$time = microtime(true);
$s = 0;
for ($i=0; $i<$M; $i++) {
$s+=calc();
}
$time2 = microtime(true)-$time;
$time = $time2/$M;
printf("%.3f\r\n", $time);
Wyniki:
PHP: 0.034s
Mono: 0.017s
Python: 0.010s
Java: 0.003s
PHP+HipHop: 0.003s
Z czego ostatni wynik nie świadczy o szybkości PHP tylko C++. HipHop for PHP działa na takiej zasadzie że przetłumacza kod PHP na C++, a następnie go kompiluje. Link do projektu: http://developers.facebook.com/hiphop-php/
P.S Sorry za podwójnego posta
Super, dzięki za kod w PHP :-)
OdpowiedzUsuńCiekawe wyniki, choć może trochę trudne do odczytania, wypadałoby chyba zwiększyć ilość powtórzeń żeby wyniki były bardziej widoczne.
Dziwne, że Mono wypadło tak słabo, ciekawe w ogóle jak Mono wypada w porównaniu do .NET na Windows.
Słyszałem o projekcie HipHop, choć nie przepadam za PHP to bardzo podoba mi się podejście Facebooka, zamiast przepisywać na "lepsze" technologie postanowili uderzyć w słabość technologii której używali dzięki czemu uzyskali chyba lepsze wyniki i to taniej niż gdyby przenieśli wszystko na jakaś "poważną" platformę.
"" z racji tego, że takie terminy jak "lepsza technologia" i "poważna" są dość umowne ;-)
kurde :F wklejałem źródła PHP ale je wywalił jakiś hmmmm zabezpieczacz przed wstrzyknięciem kodu ;) pewnie przez to, że znaczniki php dostałem :F
OdpowiedzUsuńTutaj źródła PHP
function getTime() {
list($usec, $sec) = explode(' ', microtime());
return ((float)$usec + (float)$sec);
}
$N = 10000;
$M = 1000;
function calc() {
global $N, $M;
$sum = 0;
for ($i = 0; $i < $N; $i++) {
$x = 20.0 * $i / $N - 10.0;
$sum += exp(-1*$x * $x) * (20.0 / $N);
}
return $sum;
}
$start = getTime();
$s = 0;
for ($i = 0; $i < $M; $i++) {
$s += calc();
}
$time = getTime();
echo round($time - $start,6);
co do C# jedyną zmianą jaką wprowadziłem w Twoje źródła opisałem wyżej - przeliczenie z użyciem funkcji od ticków.
Co do Javy z przełącznikiem server u mnie wydajność skoczyła mniej więcej o dwa razy - 2324
Moje wątpliwości zrodziły się z tego, że byłem przekonany, że mam już świeże źródła (te po poprawkach)
lol :F
JavaScript:
1355 - FF 3.5.8 - szybciej niż Java oO
Z ciekawości jeszcze Java ME zrobie :F (ciągnę moduły do Beans'ów)
To jeszcze moje wyniki dla przeglądarek:
OdpowiedzUsuń- Epiphany (Webkit) - 2.342
- Chrome - 2.884
- Firefox 3.6 - 6.487
- Opera 10.10 - 11.811
Operka pewnie lepiej by wypadła w najnowszej wersji 10.50, ale niestety nie mam jak tego przetestować ze względu na system (Ubuntu). Firefox też powinien mieć lepszy wynik pod Windowsem
Nie mogłem się oprzeć ;)
OdpowiedzUsuńprogram speed
real(kind=8), parameter :: e = 2.718281828459045
real(kind=8) :: x
integer(kind=2), parameter :: n = 10000
integer(kind=2) :: i, j
real(kind=8) :: wynik, t_pocz, t_koniec, pokaz
call cpu_time(t_pocz)
do j= 1,1000
sum=0.
do i = 0,10000
x = 20.*i/n-10.
wynik=e**(-x*x)*(20./n)
sum = sum + wynik
end do
end do
call cpu_time(t_koniec)
pokaz = sum
print *,'Wynik calkowania :', pokaz
print *,'Czas trwania [ms]:',t_koniec-t_pocz/1000
call sleep(15)
end
Poprawiona wersja w Fortranie 90 :)
OdpowiedzUsuńprogram speed
!Skompilowac mozna np. tak:
!gfortran -O3 -fomit-frame-pointer speed.f90 -o speed-fortran.exe
!~3.02 ms i ~2.75 ms dla wersji alternatywnej
real(kind=8), parameter :: e = 2.71828182845904524
real(kind=8) :: x
integer(kind=2), parameter :: n = 10000
integer(kind=4) :: i, j
real(kind=8) :: wynik, t_pocz, t_koniec, pokaz
call cpu_time(t_pocz)
do j= 1,1000
sum=0.
do i = 0,10000
x = 20.*i/n-10.
!wynik=exp(-x*x)*(20./n) wersja alternatywna
wynik=e**(-x*x)*(20./n)
sum = sum + wynik
end do
end do
call cpu_time(t_koniec)
pokaz = sum
print '(A,1f22.17)','Wynik calkowania :', pokaz
print '(A,1f14.9)','Czas trwania [ms]:',t_koniec-t_pocz
!call sleep jest potrzebne tylko na MS systemach
call sleep(12)
end
Laptop Firmowy Dell Latitude D830
OdpowiedzUsuńUbuntu 10.04, jądro 2.6.32-34
CPU 0 - 2.20 GHz (Intel Core 2 Duo)
CPU 1 - 2.20 GHz (Intel Core 2 Duo)
Java (1.6.0_26) : 3.246 s
Mono (v.2.4.4) : 18.903 s
Python (2.6.5) : 10.072 s
c : 1.635 s
c# (.net 4.0) RunTime 00:00:01.32
OdpowiedzUsuńjava (1.6) RunTime: 3.526 s
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace speedtest
{
class Program
{
const int N = 10000;
const int M = 1000;
static double calc()
{
double sum = 0;
for (int i = 0; i < N; i++)
{
double x = 20.0f * i / N - 10.0f;
sum += Math.Pow(Math.E, -x * x) * (20.0 / N);
}
return sum;
}
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
double s = 0;
for (int i = 0; i < M; i++)
{
s+=calc();
}
watch.Stop();
TimeSpan ts = watch.Elapsed;
// Format and display the TimeSpan value.
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
Console.ReadKey();
}
}
}
import com.google.common.base.Stopwatch;
public class Speed {
private static final int N=10000;
private static final int M=1000;
static double calc() {
double sum = 0;
for (int i=0; i<N; i++) {
double x = 20.0*i/N-10.0;
sum+=Math.pow(Math.E, -x*x)*(20.0/N);
}
return sum;
}
//public static void main(String[] args)
public static void main(String[] args) {
//long start = System.currentTimeMillis();
Stopwatch stopwatch = new Stopwatch().start();
double s=0;
for (int i=0; i<M; i++) {
s+=calc();
}
stopwatch.stop(); // optional
long millis = stopwatch.elapsedMillis();
System.out.println("RunTime: " + stopwatch);
}
}