Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz

PHP ekosisteman gaur egun bi konektore daude Tarantool zerbitzariarekin lan egiteko - hau da PECL luzapen ofiziala tarantool/tarantool-php, C-z idatzita, eta tarantool-php/bezeroa, PHPn idatzia. Azken honen egilea naiz.

Artikulu honetan, bi liburutegien errendimendu proben emaitzak partekatu nahiko nituzke eta erakutsi nola, kodean gutxieneko aldaketak eginez, 3-5 errendimendu handitzea lor dezakezun (proba sintetikoetan!).

Zer proba egingo dugu?

Goian aipatutakoak probatuko ditugu sinkronikoa asinkrono, paralelo eta asinkrono-paralelo exekutatzen diren konektoreak. πŸ™‚ Konektoreen kodea bera ere ez dugu ukitu nahi. Une honetan hainbat luzapen daude eskuragarri nahi duzuna lortzeko:

  • Swoole ― PHPrako errendimendu handiko marko asinkronoa. Alibaba eta Baidu bezalako Interneteko erraldoiek erabiltzen dute. 4.1.0 bertsioaz geroztik metodo magiko bat agertu da SwooleRuntime::enableCoroutine(), horri esker "PHP sareko liburutegi sinkronoak kode lerro batekin asinkrono bihur ditzakezu".
  • Async duela gutxi arte PHPn lan asinkronorako luzapen oso itxaropentsua zen. Zergatik duela gutxi arte? Zoritxarrez, niretzat ezezaguna den arrazoi batengatik, egileak biltegia ezabatu zuen eta proiektuaren etorkizuneko patua ez dago argi. Erabili beharko dut bat sardexketatik. Swoole-ren antzera, luzapen honek prakak eskumuturraren kolpe batekin erraz pizteko aukera ematen dizu, asinkronia gaitzeko, TCP eta TLS korronteen ezarpen estandarra bertsio asinkronoekin ordezkatuz. Hau " aukeraren bidez egiten daasync.tcp = 1".
  • Paralelo ― Joe Watkins ezagunaren luzapen nahiko berria, phpdbg, apcu, pthreads, pcov, uopz bezalako liburutegien egilea. Luzapenak hari anitzeko API bat eskaintzen du PHPn eta pthread-en ordezko gisa kokatzen da. Liburutegiaren muga esanguratsu bat PHPren ZTS (Zend Thread Safe) bertsioarekin bakarrik funtzionatzen duela da.

Nola egingo dugu proba?

Abiarazi dezagun Tarantool-en instantzia bat idatzi aurretiko erregistroa desgaituta dagoela (wal_mode = bat ere ez) eta sareko buffer handitu (irakurri aurretik = 1 * 1024 * 1024). Lehenengo aukerak diskoarekin lana ezabatuko du, bigarrenak sistema eragilearen bufferetik eskaera gehiago irakurtzea ahalbidetuko du eta, horrela, sistema dei kopurua minimizatuko du.

Datuekin lan egiten duten erreferentzietarako (txertatzea, ezabatzea, irakurtzea, etab.), erreferentea hasi aurretik, memtx espazio bat (berriro) sortuko da, indizearen balio nagusiak ordenatutako balio osoen sorgailu batek sortzen dituena. (sekuentzia).
DDL espazioak honela dauka:

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

Beharrezkoa izanez gero, erreferentea exekutatu aurretik, espazioa formularioko 10,000 tuplez betetzen da.

{id, "tuplΠ΅_<id>"}

Tuplak ausazko gako-balio bat erabiliz sartzen dira.

Erreferentzia bera zerbitzariari egindako eskaera bakarra da, 10,000 aldiz exekutatzen dena (iraultzak), eta, aldi berean, iteraziotan exekutatzen dira. Iterazioak errepikatzen dira 5 iterazioen arteko denbora-desbideratze guztiak % 3ko errore onargarri baten barruan egon arte. Horren ondoren, batez besteko emaitza hartzen da. Iterazioen artean 1 segundoko etenaldia dago prozesadoreak ez uzteko. Luaren zabor-biltzailea iterazio bakoitzaren aurretik desgaituta dago eta amaitu ondoren abiaraztera behartuta dago. PHP prozesua erreferentziarako beharrezkoak diren luzapenekin soilik abiarazten da, irteerako buffer-a gaituta eta zabor-biltzailea desgaituta.

* Erreferentziaren ezarpenetan bira, iterazio eta erroreen atalasea alda daitezke.

Proba ingurunea

Jarraian argitaratutako emaitzak MacBookPro (2015), sistema eragile batean egin dira - Fedora 30 (kernel bertsioa 5.3.8-200.fc30.x86_64). Tarantool docker-en abiarazi zen " parametroarekin--network host".

Paketeen bertsioak:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, eraiki a872fc2f86
PHP: 7.3.11 (cli) (eraikia: 22ko urriaren 2019a 08:11:04)
tarantool/bezeroa: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ 7.3rako adabakia)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12
ext-paraleloa: 1.1.3

* Zoritxarrez, konektore ofizialak ez du funtzionatzen PHP bertsio > 7.2. PHP 7.3-n luzapena konpilatzeko eta exekutatzeko, erabili behar izan nuen adabakia.

Findings

Modu sinkronikoa

Tarantool protokoloak formatu bitarra erabiltzen du Mezu paketea mezuak serializatzeko. PECL konektorean, serializazioa liburutegiaren sakonean ezkutatzen da eta kodetze prozesuari eragiten dio erabiltzaile-kodetik. ez dirudi posible. PHP konektore huts batek, aitzitik, kodetze-prozesua pertsonalizatzeko gaitasuna ematen du kodetzaile estandarra zabalduz edo zure inplementazioa erabiliz. Kutxatik kanpo bi kodetzaile daude eskuragarri, bata oinarritzen da msgpack/msgpack-php (MessagePack PECL luzapen ofiziala), bestea aktibatuta dago rybakit/msgpack (PHP hutsean).

Konektoreak alderatu aurretik, PHP konektorerako MessagePack kodetzaileen errendimendua neurtuko dugu eta proba gehiagotan emaitzarik onena erakusten duena erabiliko dugu:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
PHP bertsioa (Pure) abiadura PECL luzapena baino txikiagoa bada ere, proiektu errealetan erabiltzea gomendatuko nuke. rybakit/msgpack, MessagePack luzapen ofizialean formatuaren zehaztapena partzialki bakarrik inplementatzen delako (adibidez, ez dago datu-mota pertsonalizatuetarako euskarririk, eta hori gabe ezingo duzu Decimal erabili - Tarantool 2.3-n sartutako datu-mota berria) eta bat dauka. beste kopurua arazoak (PHP 7.4rekin bateragarritasun arazoak barne). Bada, orokorrean, proiektuak abandonatuta dirudi.

Beraz, neur dezagun konektoreen errendimendua modu sinkronoan:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Grafikoan ikus daitekeenez, PECL konektoreak (Tarantool) errendimendu hobea erakusten du PHP konektorearekin (Bezeroa) alderatuta. Baina ez da harritzekoa, azken honek, hizkuntza motelago batean inplementatzeaz gain, lan gehiago egiten duela egia esan: dei bakoitzean objektu berri bat sortzen da. Eskaera ΠΈ Response (Hautatu kasuan - ere Irizpideak, eta Eguneratu/Upsert kasuan ― Eragiketak), entitate bereiziak Konexioa, Packer ΠΈ handler gainkostua ere gehitzen dute. Jakina, malgutasunak prezioa dauka. Hala ere, orokorrean, PHP interpreteak errendimendu ona erakusten du, aldea dagoen arren, hutsala da eta, agian, are gutxiago izango da PHP 7.4-n aurrekarga erabiltzean, PHP 8-n JIT aipatzearren.

Goazen aurrera. Tarantool 2.0-k SQLrako euskarria gehitu zuen. Saia gaitezen Hautatu, Txertatu, Eguneratu eta Ezabatu eragiketak egiten SQL protokoloa erabiliz eta alderatu emaitzak noSQL (bitarreko) baliokideekin:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
SQL emaitzak ez dira oso ikusgarriak (gogora dezagun oraindik modu sinkronoa probatzen ari garela). Hala ere, ez nintzateke horren aurretik haserretuko; SQL euskarria oraindik garapen aktiboan dago (nahiko duela gutxi, adibidez, laguntza gehitu zen prestatutako adierazpenak) eta, zerrendaren arabera gaiak, SQL motorrak hainbat optimizazio jasango ditu etorkizunean.

Asinkronizatuta

Bada, orain ikus dezagun Async luzapenak goiko emaitzak hobetzen nola lagun diezagukeen. Programa asinkronoak idazteko, luzapenak koroutinetan oinarritutako API bat eskaintzen du, erabiliko duguna. Enpirikoki jakin dugu gure ingurunerako korrutina kopuru optimoa 25 dela:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
"Hedatu" 10,000 eragiketa 25 korutinetan eta ikusi zer gertatzen den:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Segundoko eragiketa kopurua 3 aldiz baino gehiago handitu da tarantool-php/bezeroa!

Zoritxarrez, PECL konektorea ez zen ext-async-arekin hasi.

Zer gertatzen da SQLrekin?

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Ikus dezakezunez, modu asinkronoan protokolo bitarraren eta SQLren arteko aldea errore-marjinaren barruan geratu zen.

Swoole

Berriz ere koroutina kopuru optimoa aurkitzen dugu, oraingoan Swoolerentzat:
Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Geldi gaitezen 25ean. Errepikatu dezagun Async luzapenarekin egiten den trikimailu bera: banatu 10,000 eragiketa 25 koroutinen artean. Horrez gain, beste proba bat gehituko dugu eta bertan lan guztia 2 bi prozesutan banatuko dugu (hau da, prozesu bakoitzak 5,000 eragiketa egingo ditu 25 korrutinatan). Prozesuak erabiliz sortuko dira SwooleProcess.

Emaitzak:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Swole-k emaitza apur bat txikiagoa erakusten du Async-ekin alderatuta prozesu batean exekutatzen denean, baina 2 prozesurekin argazkia izugarri aldatzen da (2 zenbakia ez zen kasualitatez aukeratu; nire makinan, 2 prozesu izan ziren emaitza onena erakutsi zutenak).

Bide batez, Async luzapenak prozesuekin lan egiteko API bat ere badu, baina han ez nuen desberdintasunik nabaritu prozesu batean edo gehiagotan erreferentziak exekutatzen (baliteke nonbait nahastea).

SQL vs protokolo bitarra:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Async-arekin gertatzen den bezala, eragiketa bitarren eta SQLren arteko aldea modu asinkronoan ezabatzen da.

Paralelo

Paraleloaren luzapena ez denez koroutinei buruz, hariei buruz baizik, neur dezagun hari paraleloen kopuru optimoa:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Nire makinan 16ren berdina da. Exekutatu ditzagun konektoreen erreferentziak 16 hari paralelotan:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Ikus dezakezunez, emaitza luzapen asinkronoekin baino are hobea da (Swoole 2 prozesutan exekutatzen ari den kontuan hartu gabe). Kontuan izan PECL konektorearentzat, Eguneratu eta Upsert eragiketak hutsik daudela. Eragiketa hauek errore batekin huts egin dutelako da hori - ez dakit ext-parallel, ext-tarantool edo bien errua izan den.

Orain aldera dezagun SQL-ren errendimendua:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz
Konektoreen grafikoaren antzekotasuna nabaritu duzu sinkronoki exekutatzen diren konektoreetarako?

Elkarrekin

Eta azkenik, labur ditzagun emaitza guztiak grafiko batean probatutako luzapenen irudi orokorra ikusteko. Gehitu diezaiogun proba berri bat taulari, oraindik egin ez duguna - exekutatu ditzagun Async coroutines paraleloan Parallel* erabiliz. Goiko luzapenak integratzeko ideia dagoeneko dago eztabaidatu zen egileak, baina ez zen adostasunik lortu, zuk zeuk egin beharko duzu.

* Ezin izan da Swoole koroutinak Parallel-ekin abiarazi; badirudi luzapen hauek bateraezinak direla.

Beraz, azken emaitzak:

Tarantoolerako PHP konektoreak bizkortzea Async, Swoole eta Parallel erabiliz

Horren ordez Ondorio baten

Nire ustez, emaitzak nahiko mereziak izan ziren, eta arrazoiren batengatik ziur nago hori ez dela muga! Proiektu erreal batean bakarrik erabaki behar duzun ala ez, esango dut niretzat esperimentu interesgarri bat izan zela, TCP konektore sinkrono batetik zenbat "estu dezakezun" esfortzu minimoarekin ebaluatzeko aukera ematen dizuna. Erreferentziak hobetzeko ideiak badituzu, pozik hartuko dut zure tira eskaera. Abiarazteko argibideak eta emaitzak dituen kode guztiak bereizi batean argitaratzen dira biltegiak.

Iturria: www.habr.com

Gehitu iruzkin berria