tornado performance teszt
Ha már megcsináltam, hogy tornado működjön rendesen Solarison is, akkor gondoltam meg is mérem, hogy mennyire rendes az - de legalábbis összehasonlítom az általunk használt hagyományos fascgi megoldással.
Igazából a tornadot nem WSGI appok futtatására találták ki, de azt is tudja, és hát egy tipikus python webalkalmazás belehelyezhető (jó esetben) egy WSGI konténerbe, úgyhogy miért ne. A tesztalkalmazás egy nagyon alap Django project lett, amiben nincs semmi, csak amit a django-admin.py startproject legyárt, illetve egy extra view, ami kiírja ügyesen, hogy Hello World!.
Hat féle felállást hasonlítottam össze, minden előtt volt egy nginx, azért is mert a cucc egy zónában futott, illetve mert a fastcgi-ket nem tudom közvetlen megszólítani "böngészővel":
- fastcgi/threaded
- fastcgi/prefork
- tornado/_Select
- tornado/_LibEvent
- nginx/4*tornado
- haproxy/4*tornado
A mérést az előzőhöz hasonlóan az apache féle ab programmal végeztem, a 1, 10, 100, 1000, 5000 és 10000 párhuzamos klienst szimulálva, az utolsó esetben összesen 50000, egyébként 10000 lekéréssel. Az áteresztő képességen kívül (request/sec) felírtam a kliensek 50/95/99/100%-ának kiszolgálási idejét (milisec). Utóbbi adatokból inkább nem rajzoltam grafikont ![]()
Az előzőhöz hasonló módon a teszt egy x86-os Solaris 10-on futott - nem ugyanazon a gépen -, és ugyanúgy minden tesztet háromszor futtattam le, a legjobb eredményt feljegyezve.
Grafikon az áteresztőképességekről:

Konklúzió: a tornado bizony jóval hatékonyabb, mint a sima fastcgik, pláne, ha egy többmagos/többprocesszoros gépen a processzormagok számának megfelelő mennyiségűt indítunk (...reméljük a GIL-től majd megszabadul a python, és akkor ki lehet használni a szálakat rendesen...). Ahogy látszik viszont a _Select alapú ioloopnak meg vannak a korlátai, ha valahol ezt vagyunk kénytelenek használni, ott nginx oldalon tudunk korlátozni, hogy ne kapjon egyszerre mondjuk ezernél több kérést.
Bár a haproxy gyengébben szerepelt, mint az nginx magában, az azért lehet, mert Solaris 10-en még nem támogatja az event ports féle pollingot, csak a régebbi /dev/poll féle megoldást - ennek ellenére jól teljesít, linux alatt valószínűleg ő nyert volna.
A lényeg, hogy a tornado úgy fest valóban képes megbirkózni a tízezer kliens problémájával, és django alkalmazások alatt is jól használható, ha sok klienst kell kiszolgálni.
A nyers számok, ha valakit érdekel:
| clients | r/s | 50% | 95% | 99% | 100% |
|---|---|---|---|---|---|
| fastcgi/threaded | |||||
| 1 | 721.15 | 1 | 1 | 10 | 25 |
| 10 | 365.65 | 11 | 25 | 33 | 6794 |
| 100 | 369.72 | 16 | 30 | 10126 | 23643 |
| 1000 | 166.14 | 17 | 23909 | 60139 | 60144 |
| 5000 | 164.79 | 3515 | 60304 | 60502 | 60513 |
| 10000 | timeout | ||||
| fastcgi/prefork | |||||
| 1 | 714.48 | 1 | 3 | 10 | 21 |
| 10 | 1258.66 | 4 | 14 | 68 | 3390 |
| 100 | 452.62 | 2 | 61 | 3522 | 13520 |
| 1000 | 166.18 | 3 | 23647 | 60104 | 60135 |
| 5000 | 173.40 | 5 | 54082 | 54262 | 54581 |
| 10000 | timeout | ||||
| tornado/_Select | |||||
| 1 | 1091.53 | 1 | 1 | 2 | 21 |
| 10 | 1552.47 | 6 | 11 | 16 | 108 |
| 100 | 1658.85 | 59 | 82 | 112 | 161 |
| 1000 | 487.61 | 172 | 6795 | 10235 | 10259 |
| 5000 | meghal (ValueError: filedescriptor out of range in select()) | ||||
| 10000 | meghal (ValueError: filedescriptor out of range in select()) | ||||
| tornado/_LibEvent | |||||
| 1 | 1071.32 | 1 | 1 | 2 | 109 |
| 10 | 1489.22 | 6 | 11 | 16 | 25 |
| 100 | 1576.43 | 62 | 84 | 93 | 125 |
| 1000 | 1500.64 | 145 | 3525 | 3719 | 3792 |
| 5000 | 1208.25 | 157 | 3763 | 3909 | 3968 |
| 10000 | 1155.65 | 168 | 10167 | 10611 | 10710 |
| nginx/4*tornado(_LE) | |||||
| 1 | 923.65 | 1 | 1 | 10 | 21 |
| 10 | 2396.58 | 3 | 11 | 19 | 36 |
| 100 | 3431.58 | 26 | 75 | 103 | 130 |
| 1000 | 3379.93 | 83 | 200 | 224 | 263 |
| 5000 | 3128.74 | 526 | 912 | 957 | 1112 |
| 10000 | 2615.14 | 2272 | 7725 | 7954 | 8137 |
| haproxy/4*tornado(_LE) | |||||
| 1 | 953.81 | 1 | 1 | 8 | 19 |
| 10 | 2360.69 | 3 | 12 | 21 | 33 |
| 100 | 2471.05 | 36 | 80 | 89 | 98 |
| 1000 | 2265.11 | 223 | 312 | 329 | 334 |
| 5000 | 2379.75 | 503 | 3943 | 3962 | 3992 |
| 10000 | 1703.74 | 860 | 10584 | 10816 | 10890 |