Sebesség témája

Szerencsére a böngészőgyártók versenyeznek egymással, ezért - többek között - a javascript motorok is napról napra gyorsabbak lesznek. Eszembe jutott, hogy meg kéne nézni pár egyszerű - és szuperbuta - teszttel, hogy hogyan teljesít a frissen megjelent Google V8.

Hirtelen jött az ötlet, és lusta is vagyok mindenféle grafikont rajzolni, meg bonyolult nyelvek közötti tesztcsomagot kidolgozni (egyébként van ilyen), szóval senki ne vonjon le messze menő következtetéseket :)

Először a legbutább teszt, egy ciklussal egymilliószor összekonkatenálok egy space karaktert. Ilyet - hacsaknem direkt - soha ne csináljatok, a string konkatenálás kb. az összes általam ismert nyelven eléggé munkás művelet, mert a string általában nem módosítható (immutable), ezért másolgatni kell a memóriában, meg ilyenek. A versenyzők:

  • Python 3.1.2 (Arch)

  • PHP 5.3.4 (Arch)

  • node.js (v0.3.2-pre)

És a tesztek:

a.py:

a = ""
for i in range(0,1000000):
  a = a + " "

a.php:

$a = "";
for ($i=0; $i<1000000; $i++) {
  $a = $a . " ";
}

a.js:

var i, a = "";
for (i=0; i<1000000; i++) {
  a = a + " ";
}

Eredmények (egyben, mert lusta vagyok, 5 lefutásból a középső):

$ time python a.py
python a.py  0.52s user 0.00s system 99% cpu **0.531** total

$ time php a.php
php a.php  252.13s user 0.85s system 99% cpu **4:13.21** total (wtf?)

$ time node a.js
node a.js  0.27s user 0.06s system 97% cpu **0.345** total

Meg kell jegyeznem, hogy a php-val történt valami, a legelső próbálkozás 14.52 sec alatt lefutott, de utána többet soha, mindig ilyen 4 perc körül. Próbáltam másik gépen is, ott is irgalmatlan lassú volt a pythonos verzióhoz képest. Memóriát kapott eleget, szóval nemtom...

Második teszt, ugyanez, csak úgy ahogy javaslom, azaz a string-darabkákat egy tömbbe teszem, amit a végén egyben csapok össze egy nagy stringgé.

b.py:

a = []
for i in range(0,1000000):
  a.append(" ")
"".join(a)

b.php:

$a = array();
for ($i=0; $i<1000000; $i++) {
  $a[] = " ";
}
implode("", $a);

b.js:

var i, a = [];
for (i=0; i<1000000; i++) {
  a.push(" ");
}
a.join("");

Eredmények:

$ time python b.py
python b.py  0.47s user 0.03s system 99% cpu **0.498** total

$ time php b.php
php b.php  1.36s user 0.25s system 99% cpu **1.623** total

$ time node b.js
node b.js  0.38s user 0.06s system 98% cpu **0.448** total

És végül egy tömb rendezés, egy visszafelé számoló milliós ciklussal feltöltök egy tömböt, és rendezem az elemeit.

c.py:

a = []
for i in range(1000000,0,-1):
  a.append(i)
a.sort()

c.php:

$a = array();
for ($i=1000000; $i>0; $i--) {
  $a[] = $i;
}
$s = sort($a);

c.js:

var i, a = [];
for (i=1000000; i>0; i--) {
  a.push(i);
}
a.sort(function(x,y){return x - y});

Eredmények:

$ time python c.py
python c.py  0.54s user 0.06s system 99% cpu **0.605** total

$ time php c.php
php c.php  2.67s user 0.26s system 99% cpu **2.941** total

$ time node c.js
node c.js  1.20s user 0.04s system 99% cpu **1.243** total

# inyenceknek:
$ time python -c "list(range(1000000,0,-1)).sort()"
python -c "list(range(1000000,0,-1)).sort()"  0.18s user 0.06s system 98% cpu 0.246 total

Itt a javascript egyértelmű hátránnyal indult az extra függvényhívás miatt, amit a másik két interpreter gondolom valami C-ben írt dologgal old meg, ennek ellenére elég jól teljesített.

Konklúzió

Ahogy írtam az elején, nem érdemes messze menő következtetéseket levonni. Direkt nem használtam semmi külső libet, ezért mérem a futási időt a time paranccsal, ami miatt viszont a "virtuális gépek" elindulási ideje is beleszámít a futási időbe.

Amit viszont látni szerettem volna, az látszik is, a javascript bizony egyre gyorsabb, és érdemes egyre több számításigényes műveletet kliens oldalra áttolni. Nem csak azért, mert a php-nál látványosan gyorsabb adott esetben a V8, hanem mert azzal sem a szervert terheljük :)

14dec.

6 Comment for Sebesség témája

  1. slink says:

    Érdekes, hogy az első tesztmérésednél PHP-ra én is kirívóan magas értéket kaptam, viszont némiképp módosítva a kódon, a legjobb eredményt produkálta.

    $a = $a . " " esetén:

    php a.php  155,63s user 1,24s system 98% cpu 2:39,16 total

    $a .= " "-val viszont

    php a.php  0,10s user 0,01s system 87% cpu 0,129 total
    python a.py  0,28s user 0,05s system 97% cpu 0,338 total
    

    Valami optimalizációt belevittek a srácok ezek szerint.

    PHP 5.3.3 (cli) (built: Oct 30 2010 17:01:17)
    Darwin slinkbuk.local 10.4.0 Darwin Kernel Version 10.4.0: Fri Apr 23 18:28:53 PDT 2010; root:xnu-1504.7.4~1/RELEASE_I386 i386

    • RePa says:

      Lehet, h ilyenkor karaktertombkent kezeli a php a stringet, es a vegere csapja a dolgot, viszont ez csalas a masik ket nyelvvel szemben, mert ok ilyet nem csinalnak (ha jol tudom). Egyebkent ez meggyorsabb mindnel:

      $ time python -c "a=' '*1000000"
      python -c "a=' '*1000000"  0.06s user 0.02s system 95% cpu 0.087 total

      Amugy nemis annyira a php lassusaga a meglepo, hanem a masik ketto gyorsasaga, mindenhol le van irva, hogy a string konkatenacio ilyenolyan nagyon rossz, es sose csinald, ennek ellenere ugyfest, hogy - lehet csak bizonyos esetekben - annyira nem lassu.

      • slink says:

        A csalást megerősítem azzal, hogy a a tömbbe gyűjtés jelentősen lassabb volt a .= operátoros megoldáshoz képest (0,75 vs. 0,13), és még a memória limitet is feljebb kellett állítani hozzá.

  2. rubymood says:

    Utolsó tesztnél a javascriptnél nem kell a plusz function. Anélkül is ugyan azt kapod vissza a sort függvénnyel. Gondolom így kicsit gyorsabb lesz. :)

    • RePa says:

      Nemegeszen, mert olyankor stringkent rendez sorba:

      > a = [1,2,11]
      [ 2, 1, 11 ]
      > a.sort()
      [ 1, 11, 2 ]

      Es mivel a string "rendezes" lassabb, ezert az vegeredmeny is lassabb lesz:

      $ time node d.js
      node d.js  2.82s user 0.05s system 99% cpu 2.876 total
  3. Joó Ádám says:

    A http://weblabor.hu/cikkek/web-worker címen látványos grafikon is megtekinthető.

Szólj hozzá