Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel

In die PHP-ekosisteem is daar tans twee verbindings om met die Tarantool-bediener te werk - dit is die amptelike PECL-uitbreiding tarantool/tarantool-php, geskryf in C, en tarantool-php/kliënt, geskryf in PHP. Ek is die skrywer van laasgenoemde.

In hierdie artikel wil ek graag die resultate van prestasietoetsing van beide biblioteke deel en wys hoe u, met minimale veranderinge aan die kode, 'n prestasieverhoging van 3-5 kan behaal (op sintetiese toetse!).

Wat sal ons toets?

Ons sal die bogenoemde toets sinchrone verbindings wat asinchroon, parallel en asinchronies-parallel loop. 🙂 Ons wil ook nie die kode van die verbindings self raak nie. Daar is tans verskeie uitbreidings beskikbaar om te bereik wat jy wil hê:

  • Swol ― 'n hoëprestasie asinchrone raamwerk vir PHP. Word gebruik deur internetreuse soos Alibaba en Baidu. Sedert weergawe 4.1.0 het 'n towermetode verskyn SwooleRuntime::enableCoroutine(), wat jou toelaat om "sinchroniese PHP-netwerkbiblioteke om te skakel na asinchrone met een reël kode."
  • Async was tot onlangs 'n baie belowende uitbreiding vir asynchrone werk in PHP. Hoekom tot onlangs? Ongelukkig, vir 'n rede wat vir my onbekend is, het die skrywer die bewaarplek uitgevee en die toekomstige lot van die projek is onduidelik. Ek sal dit moet gebruik een van vurke. Soos Swoole, stel hierdie uitbreiding jou in staat om jou broek maklik met 'n handbeweging aan te skakel om asinchronie moontlik te maak deur die standaardimplementering van TCP- en TLS-strome met hul asinchrone weergawes te vervang. Dit word gedoen deur die opsie "async.tcp = 1«.
  • Parallel ― 'n taamlik nuwe uitbreiding van die bekende Joe Watkins, skrywer van biblioteke soos phpdbg, apcu, pthreads, pcov, uopz. Die uitbreiding bied 'n API vir multithreading in PHP en is geposisioneer as 'n plaasvervanger vir pthreads. 'n Beduidende beperking van die biblioteek is dat dit net werk met die ZTS (Zend Thread Safe) weergawe van PHP.

Hoe sal ons toets?

Kom ons begin 'n Tarantool-instansie met voorskryf-aantekening gedeaktiveer (wal_mode = geen) en verhoogde netwerkbuffer (leesvooruit = 1 * 1024 * 1024). Die eerste opsie sal werk met die skyf uitskakel, die tweede sal dit moontlik maak om meer versoeke van die bedryfstelselbuffer te lees en sodoende die aantal stelseloproepe te verminder.

Vir maatstawwe wat met data werk (invoeging, skrap, lees, ens.), voordat die maatstaf begin word, sal 'n memtx-spasie (her)skep word, waarin die primêre indekswaardes geskep word deur 'n genereerder van geordende heelgetalwaardes ​(volgorde).
Die spasie DDL lyk soos volg:

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

Indien nodig, voordat die maatstaf uitgevoer word, word die spasie gevul met 10,000 XNUMX tupels van die vorm

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

Toegang tot tuples word verkry deur 'n ewekansige sleutelwaarde te gebruik.

Die maatstaf self is 'n enkele versoek aan die bediener, wat 10,000 5 keer uitgevoer word (omwentelings), wat op sy beurt weer in iterasies uitgevoer word. Die iterasies word herhaal totdat alle tydsafwykings tussen 3 iterasies binne 'n aanvaarbare fout van 1%* is. Hierna word die gemiddelde resultaat geneem. Daar is 'n XNUMX sekonde pouse tussen iterasies om te verhoed dat die verwerker versmoor. Lua se vullisverwyderaar word voor elke iterasie gedeaktiveer en word gedwing om te begin nadat dit voltooi is. Die PHP-proses word slegs geloods met die uitbreidings wat nodig is vir die maatstaf, met uitsetbuffering geaktiveer en die vullisverwyderaar gedeaktiveer.

* Die aantal omwentelinge, iterasies en foutdrempels kan in die maatstafinstellings verander word.

Toets omgewing

Die resultate wat hieronder gepubliseer is, is gemaak op 'n MacBookPro (2015), bedryfstelsel - Fedora 30 (kernweergawe 5.3.8-200.fc30.x86_64). Tarantool is in docker bekendgestel met die parameter "--network host".

Pakket weergawes:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, bou a872fc2f86
PHP: 7.3.11 (cli) (gebou: 22 Okt 2019 08:11:04)
tarantool/kliënt: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ pleister vir 7.3)*
ext-msgpack: 2.0.3
ext-asinc: 0.3.0-8c1da46
ext-swol: 4.4.12
ext-parallel: 1.1.3

* Ongelukkig werk die amptelike verbinding nie met PHP weergawe> 7.2 nie. Om die uitbreiding op PHP 7.3 saam te stel en uit te voer, moes ek gebruik pleister.

Bevindinge

Sinchroniese modus

Die Tarantool-protokol gebruik 'n binêre formaat MessagePack om boodskappe te serialiseer. In die PECL-verbinding is serialisering diep in die dieptes van die biblioteek versteek en beïnvloed die enkoderingsproses vanaf gebruikerslandkode lyk nie moontlik nie. 'n Suiwer PHP-koppelaar bied inteendeel die vermoë om die enkoderingsproses aan te pas deur die standaard-enkodeerder uit te brei of deur jou eie implementering te gebruik. Daar is twee enkodeerders uit die boks beskikbaar, een is gebaseer op msgpack/msgpack-php (amptelike MessagePack PECL-uitbreiding), die ander is aan rybakit/msgpack (in suiwer PHP).

Voordat ons verbindings vergelyk, sal ons die werkverrigting van MessagePack-enkodeerders vir die PHP-koppelaar meet en in verdere toetse sal ons die een gebruik wat die beste resultaat toon:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Alhoewel die PHP-weergawe (Pure) minderwaardig is as die PECL-uitbreiding in spoed, sal ek dit steeds aanbeveel om dit in regte projekte te gebruik rybakit/msgpack, want in die amptelike MessagePack-uitbreiding word die formaatspesifikasie slegs gedeeltelik geïmplementeer (byvoorbeeld, daar is geen ondersteuning vir persoonlike datatipes nie, waarsonder jy nie Desimaal sal kan gebruik nie - 'n nuwe datatipe wat in Tarantool 2.3 bekendgestel is) en het 'n aantal ander probleme (insluitend verenigbaarheidsprobleme met PHP 7.4). Wel, oor die algemeen lyk die projek verlate.

Dus, kom ons meet die werkverrigting van verbindings in sinchroniese modus:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Soos uit die grafiek gesien kan word, toon die PECL-koppelaar (Tarantool) beter werkverrigting in vergelyking met die PHP-koppelaar (kliënt). Maar dit is nie verbasend nie, aangesien laasgenoemde, benewens dat dit in 'n stadiger taal geïmplementeer word, eintlik meer werk doen: 'n nuwe voorwerp word met elke oproep geskep Vra и reaksie (in die geval van Kies - ook Kriteria, en in die geval van Update/Upsert ― bedrywighede), individuele entiteite verband, Packer и hanteerder hulle voeg ook bokoste by. Uiteraard kom buigsaamheid teen 'n prys. Oor die algemeen toon die PHP-tolk egter goeie werkverrigting, alhoewel daar 'n verskil is, is dit onbeduidend en sal miskien selfs minder wees wanneer vooraflaai in PHP 7.4 gebruik word, om nie eens te praat van JIT in PHP 8 nie.

Kom ons gaan aan. Tarantool 2.0 het ondersteuning vir SQL bygevoeg. Kom ons probeer om Kies-, Invoeg-, Update- en Delete-bewerkings uit te voer deur die SQL-protokol te gebruik en vergelyk die resultate met die noSQL (binêre) ekwivalente:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Die SQL-resultate is nie baie indrukwekkend nie (laat ek jou daaraan herinner dat ons steeds sinchroniese modus toets). Ek sal egter nie voor die tyd ontsteld raak nie; SQL-ondersteuning is nog aktief ontwikkel (betreklik onlangs, byvoorbeeld, is ondersteuning bygevoeg verklarings voorberei) en, te oordeel aan die lys kwessies, sal die SQL-enjin in die toekoms 'n aantal optimaliserings ondergaan.

Asynk

Wel, kom ons kyk nou hoe die Async-uitbreiding ons kan help om die resultate hierbo te verbeter. Om asynchrone programme te skryf, bied die uitbreiding 'n API gebaseer op koroutines, wat ons sal gebruik. Ons vind empiries uit dat die optimale aantal koroutines vir ons omgewing 25 is:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
"Verspreid" 10,000 25 bedrywighede oor XNUMX koroutines en kyk wat gebeur:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Die aantal operasies per sekonde het met meer as 3 keer toegeneem vir tarantool-php/kliënt!

Ongelukkig het die PECL-koppelaar nie met ext-async begin nie.

Wat van SQL?

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Soos u kan sien, het die verskil tussen die binêre protokol en SQL in die asynchrone modus binne die foutmarge geword.

Swol

Weereens vind ons die optimale aantal koroutines uit, hierdie keer vir Swoole:
Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Kom ons stop by 25. Kom ons herhaal dieselfde truuk as met die Async-uitbreiding - versprei 10,000 25 bewerkings tussen 2 koroutines. Daarbenewens sal ons nog 'n toets byvoeg waarin ons al die werk in 5,000 twee prosesse sal verdeel (dit wil sê, elke proses sal 25 XNUMX bewerkings in XNUMX koroutines uitvoer). Prosesse sal geskep word met behulp van SwooleProses.

Resultate:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Swole wys 'n effens laer resultaat in vergelyking met Async wanneer dit in een proses uitgevoer word, maar met 2 prosesse verander die prentjie dramaties (die nommer 2 is nie toevallig gekies nie; op my masjien was dit 2 prosesse wat die beste resultaat getoon het).

Terloops, die Async-uitbreiding het ook 'n API om met prosesse te werk, maar daar het ek geen verskil opgemerk om maatstawwe in een of meer prosesse te laat loop nie (dit is moontlik dat ek iewers gemors het).

SQL vs binêre protokol:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Soos met Async, word die verskil tussen binêre en SQL-bewerkings in asynchrone modus uitgeskakel.

Parallel

Aangesien die parallelle uitbreiding nie oor koroutines gaan nie, maar oor drade, kom ons meet die optimale aantal parallelle drade:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Dit is gelyk aan 16 op my masjien. Kom ons stel koppelmaatstawwe op 16 parallelle drade:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Soos u kan sien, is die resultaat selfs beter as met asynchrone uitbreidings (nie Swoole ingereken wat op 2 prosesse loop nie). Let daarop dat vir die PECL-koppelaar, die Update- en Upsert-bewerkings leeg is. Dit is te wyte aan die feit dat hierdie bewerkings misluk het met 'n fout - ek weet nie of dit die fout was van ext-parallel, ext-tarantool, of albei nie.

Kom ons vergelyk nou SQL-prestasie:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel
Let op die ooreenkoms met die grafiek vir verbindings wat sinchronies loop?

Saam

En laastens, laat ons al die resultate in een grafiek opsom om die algehele prentjie vir die getoetsde uitbreidings te sien. Kom ons voeg net een nuwe toets by die grafiek, wat ons nog nie gedoen het nie - kom ons hardloop Async-koroutines parallel met Parallel*. Die idee om bogenoemde uitbreidings te integreer is reeds bespreek is skrywers, maar geen konsensus bereik is nie, sal jy dit self moet doen.

* Dit was nie moontlik om Swoole-koroutines met Parallel bekend te stel nie; dit blyk dat hierdie uitbreidings onversoenbaar is.

Dus, die finale resultate:

Versnel PHP-verbindings vir Tarantool met behulp van Async, Swoole en Parallel

In plaas daarvan om 'n gevolgtrekking

Na my mening was die resultate redelik waardig, en om een ​​of ander rede is ek seker dat dit nie die limiet is nie! Of jy dit in 'n regte projek uitsluitlik vir jouself moet besluit, ek sal net sê dat dit vir my 'n interessante eksperiment was wat jou toelaat om te evalueer hoeveel jy met minimale moeite uit 'n sinchrone TCP-koppelaar kan "druk". As jy idees het om maatstawwe te verbeter, sal ek graag jou trekversoek oorweeg. Alle kode met bekendstellingsinstruksies en resultate word in 'n aparte gepubliseer bewaarplekke.

Bron: will.com

Voeg 'n opmerking