Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel

Yn it PHP-ekosysteem binne d'r op it stuit twa ferbiningen foar wurkjen mei de Tarantool-tsjinner - dit is de offisjele PECL-útwreiding tarantool/tarantool-php, skreaun yn C, en tarantool-php/client, skreaun yn PHP. Ik bin de skriuwer fan dat lêste.

Yn dit artikel wol ik de resultaten fan prestaasjestesten fan beide bibleteken diele en sjen litte hoe't jo, mei minimale feroarings oan 'e koade, in prestaasjesferheging fan 3-5 kinne berikke (op syntetyske tests!).

Wat sille wy testen?

Wy sille de hjirboppe neamde testen syngroane Anschlüsse rinne asynchronously, parallel, en asynchronously-parallel. 🙂 Wy wolle ek net oanreitsje de koade fan de Anschlüsse sels. D'r binne op it stuit ferskate tafoegings beskikber om te berikken wat jo wolle:

  • Swolle ― in asynchrone ramt mei hege prestaasjes foar PHP. Brûkt troch sokke ynternetgiganten as Alibaba en Baidu. Sûnt ferzje 4.1.0 is in magyske metoade ferskynd SwooleRuntime::enableCoroutine(), wêrtroch jo "syngroane PHP-netwurkbiblioteken kinne konvertearje nei asynchrone mei ien rigel koade."
  • Async wie oant koartlyn in heul promovende útwreiding foar asynchrone wurk yn PHP. Wêrom oant koartlyn? Spitigernôch hat de auteur om in my ûnbekende reden it repository wiske en it takomstige lot fan it projekt is ûndúdlik. Ik sil it brûke moatte ien fan foarken. Lykas Swoole lit dizze tafoeging jo jo broek maklik oansette mei in flick fan 'e pols om asynchrony yn te skeakeljen troch de standert ymplemintaasje fan TCP- en TLS-streamen te ferfangen mei har asynchrone ferzjes. Dit wurdt dien troch de opsje "async.tcp = 1".
  • Parallel ― in frij nije útwreiding fan de bekende Joe Watkins, skriuwer fan sokke biblioteken as phpdbg, apcu, pthreads, pcov, uopz. De tafoeging leveret in API foar multithreading yn PHP en is gepositioneerd as ferfanging foar pthreads. In wichtige beheining fan 'e bibleteek is dat it allinich wurket mei de ZTS (Zend Thread Safe) ferzje fan PHP.

Hoe sille wy testen?

Litte wy in Tarantool-eksimplaar starte mei skriuw-foarút-logging útskeakele (wal_mode = gjin) en ferhege netwurkbuffer (readahead = 1 * 1024 * 1024). De earste opsje sil elimineren wurk mei de skiif, de twadde sil meitsje it mooglik om te lêzen mear oanfragen út de bestjoeringssysteem buffer en dêrmei minimalisearje it oantal systeem oproppen.

Foar benchmarks dy't wurkje mei gegevens (ynfoegje, wiskje, lêzen, ensfh.), foardat de benchmark begjint, sil in memtx-romte (op 'e nij) oanmakke wurde, wêryn't de primêre yndekswearden wurde makke troch in generator fan oardere heule getalwearden (sekwinsje).
De romte DDL sjocht der sa út:

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}})

As it nedich is, foardat de benchmark útfiert, wurdt de romte fol mei 10,000 tuples fan it formulier

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

Tuples wurde tagong mei in willekeurige kaai wearde.

De benchmark sels is in inkeld fersyk oan de tsjinner, dy't 10,000 kear (revolúsjes) wurdt útfierd, dy't op har beurt yn iteraasjes wurde útfierd. De iteraasjes wurde werhelle oant alle tiidôfwikingen tusken 5 iteraasjes binnen in akseptabele flater fan 3%* binne. Dêrnei wurdt it gemiddelde resultaat nommen. D'r is in pauze fan 1 sekonde tusken iteraasjes om te foarkommen dat de prosessor smoart. Lua's garbage collector is foar elke iteraasje útskeakele en wurdt twongen om te begjinnen nei't it foltôge is. It PHP-proses wurdt allinich lansearre mei de útwreidingen dy't nedich binne foar de benchmark, mei útfierbuffer ynskeakele en de garbage collector útskeakele.

* It oantal revolúsjes, iteraasjes en drompel foar flaters kinne wurde feroare yn 'e benchmarkynstellingen.

Testomjouwing

De hjirûnder publisearre resultaten waarden makke op in MacBookPro (2015), bestjoeringssysteem - Fedora 30 (kernelferzje 5.3.8-200.fc30.x86_64). Tarantool waard lansearre yn docker mei de parameter "--network host".

Pakketferzjes:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, bouwe a872fc2f86
PHP: 7.3.11 (cli) (boud: 22 oktober 2019 08:11:04)
tarantool / kliïnt: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ patch foar 7.3)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swolle: 4.4.12
ext-parallel: 1.1.3

* Spitigernôch wurket de offisjele ferbining net mei PHP ferzje> 7.2. Om de útwreiding op PHP 7.3 te kompilearjen en út te fieren, moast ik brûke patch.

Resultaten

Syngroane modus

It Tarantool-protokol brûkt in binêre opmaak MessagePack om berjochten te serialisearjen. Yn 'e PECL-ferbining is serialisaasje djip yn' e djipten fan 'e bibleteek ferburgen en beynfloedet it kodearringsproses fan brûkerslânkoade liket net mooglik. In suvere PHP-ferbining, krekt oarsom, jout de mooglikheid om it kodearringsproses oan te passen troch de standert encoder út te wreidzjen of troch jo eigen ymplemintaasje te brûken. D'r binne twa encoders beskikber út 'e doaze, ien is basearre op msgpack/msgpack-php (offisjele MessagePack PECL-útwreiding), de oare is oan rybakit/msgpack (yn suver PHP).

Foardat wy ferbiners fergelykje, sille wy de prestaasjes mjitte fan MessagePack-encoders foar de PHP-ferbining en yn fierdere tests sille wy dejinge brûke dy't it bêste resultaat toant:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
Hoewol de PHP-ferzje (Pure) ynferior is foar de PECL-útwreiding yn snelheid, yn echte projekten soe ik it noch oanrikkemandearje om it te brûken rybakit/msgpack, om't yn 'e offisjele MessagePack-útwreiding de opmaakspesifikaasje mar foar in part ymplementearre is (d'r is bygelyks gjin stipe foar oanpaste gegevenstypen, sûnder dat jo Desimaal net kinne brûke - in nij gegevenstype yntrodusearre yn Tarantool 2.3) en hat in oantal oaren problemen (ynklusyf kompatibiliteitsproblemen mei PHP 7.4). No, yn 't algemien liket it projekt ferlitten.

Dat, lit ús de prestaasjes fan connectors mjitte yn syngroane modus:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
As kin sjoen wurde út de grafyk, de PECL connector (Tarantool) toant bettere prestaasjes yn ferliking mei de PHP connector (Client). Mar dit is net ferrassend, om't de lêste, neist it ymplementearre yn in stadigere taal, eins mear wurk docht: in nij objekt wurdt makke mei elke oprop Fersyk и Antwurd (yn it gefal fan Selektearje - ek Kriteria, en yn it gefal fan Update/Upsert - Operations), yndividuele entiteiten Ferbining, packer и Handler se foegje ek overhead ta. Fansels komt fleksibiliteit foar in priis. Yn 't algemien toant de PHP-interpreter lykwols goede prestaasjes, hoewol d'r in ferskil is, it is ûnbelangryk en, miskien, sil noch minder wêze by it brûken fan preloading yn PHP 7.4, net te hawwen oer JIT yn PHP 8.

Lit ús fierder gean. Tarantool 2.0 yntrodusearre SQL-stipe. Litte wy besykje operaasjes selektearje, ynfoegje, bywurkje en wiskje út te fieren mei it SQL-protokol en de resultaten fergelykje mei de noSQL (binêre) ekwivalinten:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
De SQL-resultaten binne net heul yndrukwekkend (lit my jo herinnerje dat wy noch de syngroane modus testen). Ik soe dit lykwols net foartiid oerstjoer meitsje; SQL-stipe is noch yn aktive ûntwikkeling (relatyf koartlyn is bygelyks stipe tafoege tariede útspraken) en, beoardielje troch de list saken, de SQL-motor sil yn 'e takomst in oantal optimisaasjes ûndergean.

async

No, litte wy no sjen hoe't de Async-útwreiding ús kin helpe om de resultaten hjirboppe te ferbetterjen. Om asynchrone programma's te skriuwen, leveret de tafoeging in API basearre op koroutines, dy't wy sille brûke. Wy fine empirysk út dat it optimale oantal koroutines foar ús omjouwing 25 is:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
"Fersprieden" 10,000 operaasjes oer 25 coroutines en sjoch wat der bart:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
It oantal operaasjes per sekonde tanommen mei mear as 3 kear foar tarantool-php/client!

Spitigernôch begon de PECL-ferbining net mei ext-async.

Hoe sit it mei SQL?

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
Sa't jo sjen kinne, yn asynchrone modus waard it ferskil tusken it binêre protokol en SQL binnen de marzje fan flater.

Swolle

Nochris fine wy ​​​​it optimale oantal koroutines, dizze kear foar Swoole:
Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
Litte wy stopje by 25. Litte wy deselde trúk werhelje as mei de Async-útwreiding - fersprieden 10,000 operaasjes tusken 25 coroutines. Derneist sille wy in oare test tafoegje wêryn wy al it wurk sille ferdiele yn 2 twa prosessen (dat is, elk proses sil 5,000 operaasjes útfiere yn 25 coroutines). Prosessen sille wurde makke mei SwolleProcess.

Resultaten:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
Swole toant in wat leger resultaat yn ferliking mei Async doe't rinne yn ien proses, mar mei 2 prosessen feroaret de foto dramatysk (it getal 2 waard net keazen by tafal; op myn masine, it wie 2 prosessen dy't toande it bêste resultaat).

Trouwens, de Async-útwreiding hat ek in API foar it wurkjen mei prosessen, mar dêr haw ik gjin ferskil opmurken fan it útfieren fan benchmarks yn ien of mear prosessen (it is mooglik dat ik earne ferkeard haw).

SQL vs binêr protokol:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
Lykas by Async wurdt it ferskil tusken binêre en SQL-operaasjes yn asynchrone modus elimineare.

Parallel

Om't de Parallel-útwreiding net oer coroutines giet, mar oer threads, litte wy it optimale oantal parallelle threaden mjitte:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
It is 16 op myn masine. Litte wy ferbinerbenchmarks útfiere op 16 parallelle triedden:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
Sa't jo sjen kinne, is it resultaat noch better dan mei asynchrone útwreidingen (net telle fan Swoole dy't rint op 2 prosessen). Tink derom dat foar de PECL-ferbining de operaasjes Update en Upsert leech binne. Dit komt troch it feit dat dizze operaasjes mislearre mei in flater - ik wit net as it de skuld wie fan ext-parallel, ext-tarantool, of beide.

Litte wy no SQL-prestaasjes fergelykje:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel
Merken de oerienkomst mei de grafyk foar Anschlüsse dy't syngroan rinne?

Mei-inoar

En as lêste, litte wy alle resultaten yn ien grafyk gearfetsje om it algemiene byld te sjen foar de testen tafoegings. Litte wy mar ien nije test tafoegje oan 'e kaart, dy't wy noch net hawwe dien - litte wy Async-coroutines parallel útfiere mei Parallel *. It idee om de boppesteande útwreidingen te yntegrearjen is al besprutsen skriuwers, mar gjin konsensus waard berikt, do silst moatte dwaan it sels.

* It wie net mooglik om Swoole-koroutines te starten mei Parallel; it liket derop dat dizze tafoegings ynkompatibel binne.

Dus, de definitive resultaten:

Fersnelle PHP-ferbiningen foar Tarantool mei Async, Swoole en Parallel

Yn stee fan in konklúzje

Yn myn miening, de resultaten bliken te wêzen hiel weardich, en foar guon reden ik bin der wis fan dat dit is net de limyt! Oft jo moatte beslute dit yn in echte projekt allinnich foar dysels, Ik sil allinne sizze dat foar my wie it in nijsgjirrich eksperimint wêrmei jo te evaluearjen hoefolle kinne jo "squeeze" út in syngroane TCP Connector mei minimale ynspannings . As jo ​​ideeën hawwe foar it ferbetterjen fan benchmarks, sil ik jo pull-oanfraach graach beskôgje. Alle koade mei lansearring ynstruksjes en resultaten wurdt publisearre yn in apart repositories.

Boarne: www.habr.com

Add a comment