czwartek, października 22, 2009

C# i Java okazały się szybsza od Pythona :-) [było Java okazała się szybsza od C# i Pythona]

[update: 15/01/2010 - okazało się, że pomiary dla C# były źle przeprowadzane co zaniżało jego wydajność mniej więcej o 10 razy!!!! Błędnie użyłem DateTime.Now.Ticks zakładając, że zwraca ilość naonsekund, a zwraca ilość ticków, których w nanosekundzie mieści się dziesięć. Niestety nikt tego wcześniej nie zauważył i złe wyniki poszły w świat. [tytuł posta też zmieniony ;-)]]
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:
f(x)=e-x2

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]:

.


Język/ProcesorAMD Turion64 ML-30*Intel Core Duo 2.16 GHzCeleron 900 MHz [Asus EEE]

.


Cb/d4 ms4 ms

.


Java18 ms10 ms10 ms

.


C# [wyniki powinny zostać prawdopodobnie podzielone przez 10 z racji błędu w programie testowym]45 ms32 ms34 ms

.


Python60-74 ms**27 ms30.5 ms

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 ;-)
Język Go dla Windows :-)
A JavaScript i tak szybszy ;-)