PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával

A PHP ökoszisztémában jelenleg két csatlakozó található a Tarantool szerverrel való együttműködéshez – ez a hivatalos PECL kiterjesztés tarantool/tarantool-php, C betűvel írva, és tarantool-php/kliens, PHP-ben írva. Ez utóbbinak én vagyok a szerzője.

Ebben a cikkben szeretném megosztani mindkét könyvtár teljesítménytesztének eredményeit, és bemutatni, hogyan lehet minimális kódmódosítással 3-5 teljesítménynövekedést elérni (szintetikus teszteken!).

Mit fogunk tesztelni?

A fent említetteket teszteljük szinkron aszinkron, párhuzamos és aszinkron-párhuzamos csatlakozók. 🙂 Maguk a csatlakozók kódjához sem szeretnénk hozzányúlni. Jelenleg több bővítmény is elérhető a kívánt eléréséhez:

  • Swoole ― egy nagy teljesítményű aszinkron keretrendszer a PHP-hez. Olyan internetes óriások használják, mint az Alibaba és a Baidu. A 4.1.0-s verzió óta megjelent egy varázslatos módszer SwooleRuntime::enableCoroutine(), amely lehetővé teszi a „szinkron PHP hálózati könyvtárak aszinkronokká alakítását egy sor kóddal”.
  • Az Async egészen a közelmúltig nagyon ígéretes kiterjesztése volt az aszinkron munkához a PHP-ben. Miért egészen a közelmúltig? Sajnos számomra ismeretlen okból a szerző törölte az adattárat, így a projekt további sorsa nem világos. muszáj lesz használnom egy villákból. A Swoole-hoz hasonlóan ez a bővítmény is lehetővé teszi, hogy egy csuklómozdulattal könnyedén felkapcsolja a nadrágot, hogy lehetővé tegye az aszinkront, mivel a TCP és TLS adatfolyamok szabványos megvalósítását az aszinkron verziókra cseréli. Ez a „async.tcp = 1”.
  • Párhuzamos ― egy meglehetősen új bővítmény a jól ismert Joe Watkinstól, olyan könyvtárak szerzőjétől, mint a phpdbg, apcu, pthreads, pcov, uopz. A kiterjesztés API-t biztosít a többszálú futtatáshoz PHP-ben, és a pthread helyettesítőjeként van elhelyezve. A könyvtár jelentős korlátja, hogy csak a PHP ZTS (Zend Thread Safe) verziójával működik.

Hogyan teszteljük?

Indítsunk el egy Tarantool-példányt, ahol az előreírási naplózás le van tiltva (wal_mode = nincs) és megnövelt hálózati puffer (előreolvasás = 1 * 1024 * 1024). Az első opció kiküszöböli a lemezzel való munkát, a második lehetővé teszi több kérés beolvasását az operációs rendszer pufferéből, és ezáltal minimalizálja a rendszerhívások számát.

Az adatokkal működő benchmarkok esetében (beszúrás, törlés, olvasás stb.) a benchmark elindítása előtt (újra) létrejön egy memtx tér, amelyben az elsődleges indexértékeket egy rendezett egész értékek generátora hozza létre. (szekvencia).
A DDL tér így néz ki:

space = box.schema.space.create(config.space_name, {id = config.space_id, temporary = true})
space:create_index('primary', {type = 'tree', parts = {1, 'unsigned'}, sequence = true})
space:format({{name = 'id', type = 'unsigned'}, {name = 'name', type = 'string', is_nullable = false}})

Ha szükséges, a benchmark futtatása előtt a helyet kitöltjük az űrlap 10,000 XNUMX sorával

{id, "tuplе_<id>"}

A sorok véletlenszerű kulcsértékkel érhetők el.

Maga a benchmark egyetlen kérés a szerverhez, amely 10,000 5-szer (fordulat) hajtódik végre, amelyek viszont iterációkban hajtódnak végre. Az iterációkat addig ismételjük, amíg az 3 iteráció közötti összes időeltérés 1%-os* elfogadható hibahatáron belül van. Ezt követően az átlagos eredményt veszik. Az iterációk között XNUMX másodperces szünet van, hogy megakadályozza a processzor leállását. A Lua szemétgyűjtője minden iteráció előtt le van tiltva, és a befejezése után kénytelen elindulni. A PHP folyamat csak a benchmarkhoz szükséges bővítményekkel indul, a kimeneti pufferelés engedélyezve és a szemétgyűjtő letiltása mellett.

* A fordulatok száma, az iterációk és a hibaküszöb a benchmark beállításokban módosítható.

Tesztkörnyezet

Az alábbiakban közzétett eredmények MacBookPro (2015) operációs rendszerrel készültek - Fedora 30 (kernel verzió 5.3.8-200.fc30.x86_64). A Tarantool elindult a dockerben a " paraméterrel--network host".

Csomag verziók:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, build a872fc2f86
PHP: 7.3.11 (cli) (építve: 22. október 2019., 08:11:04)
tarantool/kliens: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ patch a 7.3-hoz)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12
ext-párhuzamos: 1.1.3

* Sajnos a hivatalos csatlakozó nem működik PHP > 7.2 verzióval. A kiterjesztés lefordításához és futtatásához PHP 7.3-on kellett használnom tapasz.

Álláspontja

Szinkron mód

A Tarantool protokoll bináris formátumot használ MessagePack üzenetek sorba rendezésére. A PECL-összekötőben a szerializálás a könyvtár mélyén rejtőzik, és hatással van a kódolási folyamatra a userland kódból nem tűnik lehetségesnek. Ezzel szemben a tiszta PHP-csatlakozó lehetővé teszi a kódolási folyamat testreszabását a szabványos kódoló kiterjesztésével vagy a saját megvalósítás használatával. Két kódoló áll rendelkezésre a dobozból, az egyik alapja msgpack/msgpack-php (hivatalos MessagePack PECL kiterjesztés), a másik be van kapcsolva rybakit/msgpack (tiszta PHP-ben).

A csatlakozók összehasonlítása előtt megmérjük a PHP-csatlakozó MessagePack kódolóinak teljesítményét, és a további tesztekben azt használjuk, amelyik a legjobb eredményt mutatja:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Bár a PHP verzió (Pure) sebességében gyengébb a PECL-kiterjesztésnél, valós projektekben továbbra is javaslom a használatát. rybakit/msgpack, mert a hivatalos MessagePack kiterjesztésben a formátumspecifikáció csak részben valósult meg (például nincs támogatás az egyéni adattípusokhoz, ami nélkül nem fogja tudni használni a Decimal-t – a Tarantool 2.3-ban bevezetett új adattípust), és rendelkezik egy mások száma problémák (beleértve a PHP 7.4-gyel való kompatibilitási problémákat). Nos, a projekt általában elhagyottnak tűnik.

Tehát mérjük meg a csatlakozók teljesítményét szinkron módban:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Amint az a grafikonon látható, a PECL csatlakozó (Tarantool) jobb teljesítményt mutat a PHP csatlakozóhoz (Client) képest. De ez nem meglepő, hiszen az utóbbi amellett, hogy lassabb nyelven implementálódik, valójában több munkát végez: minden hívással új objektum jön létre. Kérjen и Válasz (a Select esetében - szintén Kritériumai, és az Update/Upsert esetén ― Művelet), külön entitások csatlakozás, csomagoló и Handler hozzáadnak rezsit is. Nyilvánvaló, hogy a rugalmasságnak ára van. Általában azonban a PHP interpreter jó teljesítményt mutat, bár van különbség, ez jelentéktelen, és talán még kevesebb lesz, ha PHP 7.4-ben előtöltést használunk, nem beszélve a JIT-ről a PHP 8-ban.

Menjünk tovább. A Tarantool 2.0 támogatja az SQL-t. Próbáljuk meg végrehajtani a Select, Insert, Update és Delete műveleteket az SQL protokoll segítségével, és hasonlítsuk össze az eredményeket a noSQL (bináris) megfelelőivel:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Az SQL eredmények nem túl lenyűgözőek (hadd emlékeztesselek arra, hogy még mindig teszteljük a szinkron módot). Ezen azonban nem idegeskednék előre, az SQL-támogatás még mindig aktív fejlesztés alatt áll (viszonylag nemrégiben pl. elkészített nyilatkozatok) és a listából ítélve kérdések, az SQL-motor a jövőben számos optimalizáláson megy keresztül.

Aszinkron

Nos, most nézzük meg, hogyan segíthet az Async bővítmény a fenti eredmények javításában. Az aszinkron programok írásához a bővítmény egy korutinokon alapuló API-t biztosít, amelyet használni fogunk. Tapasztalati úton megállapítjuk, hogy környezetünk számára a korutinok optimális száma 25:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
„Ossza el” 10,000 25 műveletet XNUMX korutin között, és nézze meg, mi történik:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
A másodpercenkénti műveletek száma több mint háromszorosára nőtt a esetében tarantool-php/kliens!

Sajnos a PECL csatlakozó nem ext-async-vel indult.

Mi a helyzet az SQL-lel?

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Mint látható, aszinkron módban a bináris protokoll és az SQL közötti különbség a hibahatáron belülre került.

Swoole

Ismét megtudjuk a korutinok optimális számát, ezúttal a Swoole esetében:
PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Álljunk meg 25-nél. Ismételjük meg ugyanazt a trükköt, mint az Async kiterjesztésnél – osszuk el 10,000 25 műveletet 2 korutin között. Ezen kívül még egy tesztet adunk hozzá, amelyben az összes munkát 5,000 két folyamatra osztjuk (vagyis mindegyik folyamat 25 műveletet hajt végre XNUMX korutinban). A folyamatok a segítségével jönnek létre SwooleProcess.

Eredmények:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
A Swole egy folyamatban futtatva valamivel gyengébb eredményt mutat az Async-hez képest, de 2 processznél drámaian megváltozik a kép (a 2-es számot nem véletlenül választottuk, az én gépemen 2 processz mutatta a legjobb eredményt).

Egyébként az Async kiterjesztésnek is van API-ja a folyamatokkal való munkavégzéshez, de ott nem vettem észre semmi különbséget a benchmarkok futtatásához képest egy vagy több folyamatban (lehet, hogy valahol elrontottam).

SQL vs bináris protokoll:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Az Asynchez hasonlóan a bináris és SQL műveletek közötti különbség aszinkron módban megszűnik.

Párhuzamos

Mivel a Párhuzamos kiterjesztés nem korutinokról, hanem szálakról szól, mérjük meg a párhuzamos szálak optimális számát:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Az én gépemen 16-nak felel meg. Futtassunk csatlakozási teszteket 16 párhuzamos szálon:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Amint látható, az eredmény még jobb, mint az aszinkron kiterjesztéseknél (nem számítva a 2 folyamaton futó Swoole-t). Vegye figyelembe, hogy a PECL-csatlakozó esetében az Update és az Upsert műveletek üresek. Ez annak a ténynek köszönhető, hogy ezek a műveletek hibával meghiúsultak - nem tudom, hogy az ext-parallel, az ext-tarantool vagy mindkettő hibája volt.

Most pedig hasonlítsuk össze az SQL teljesítményét:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával
Észreveszi a hasonlóságot a szinkronban futó csatlakozók grafikonjával?

Együtt

Végül pedig foglaljuk össze az összes eredményt egy grafikonon, hogy lássuk a tesztelt bővítmények összképét. Csak egy új tesztet adjunk a diagramhoz, amit még nem tettünk meg – futtassuk párhuzamosan az Async korutinokat a Parallel* segítségével. A fenti bővítmények integrálásának ötlete már megvan megbeszélték szerzők, de nem született konszenzus, ezt magának kell megtennie.

* A Swoole korutinokat nem lehetett elindítani a Parallel segítségével, úgy tűnik, hogy ezek a kiterjesztések nem kompatibilisek.

Szóval a végeredmény:

PHP-csatlakozók gyorsítása a Tarantool-hoz Async, Swoole és Parallel használatával

Ahelyett, hogy egy következtetés

Véleményem szerint az eredmények egészen méltónak bizonyultak, és valamiért biztos vagyok benne, hogy ez nem a határ! Hogy ezt egy valós projektben kizárólag magadnak kell eldöntened, csak annyit mondok, hogy számomra ez egy érdekes kísérlet volt, amivel felmérheted, hogy minimális erőfeszítéssel mennyit tudsz "kifacsarni" egy szinkron TCP-csatlakozóból. Ha vannak ötletei a benchmarkok javítására, szívesen megfontolom húzási kérését. Az összes kódot az indítási utasításokkal és eredményekkel együtt külön közzétesszük adattárak.

Forrás: will.com

Hozzászólás