Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel

NĂ« ekosistemin PHP aktualisht egzistojnĂ« dy konektorĂ« pĂ«r tĂ« punuar me serverin Tarantool ― kjo Ă«shtĂ« zgjerimi zyrtar PECL tarantool/tarantool-php, i shkruar nĂ« C, dhe tarantool-php/client, i shkruar nĂ« PHP. UnĂ« jam autori i kĂ«tij tĂ« fundit.

Në këtë artikull do të doja të ndaja rezultatet e testimit të performancës së të dy bibliotekave dhe të tregoj se si me ndryshime minimale në kod mund të arrihet një rritje prej 3-5 përqindësh (në teste sintetike!).

ÇfarĂ« do tĂ« testojmĂ«?

Do të testojmë të përmendurat më sipër konektorët sinkronë

― njĂ« zgjerim tĂ«rheqĂ«s nga i njohuri Joe Watkins, autori i biblioteka si phpdbg, apcu, pthreads, pcov, uopz. Zgjerimi ofron njĂ« API pĂ«r punĂ« me shumĂ« tela nĂ« PHP dhe pozicionohet si zĂ«vendĂ«sim pĂ«r pthreads. NjĂ« kufizim tĂ« rĂ«ndĂ«sishĂ«m tĂ« bibliotekĂ«s Ă«shtĂ« se ajo punon vetĂ«m me versionin ZTS (Zend Thread Safe) tĂ« PHP.

Si do t’i testojmĂ«?Do tĂ« nisim njĂ« instancĂ« tĂ« Tarantool-it pa activizimin e regjistrit tĂ« paraparĂ« (wal_mode = none) dhe me njĂ« buffer rrjeti tĂ« pĂ«rmirĂ«suar (readahead = 1 * 1024 * 1024

). Opcioni i parë do të përjashtojë punën me diskun, ndërsa i dyti do të lejojë leximin e më shumë kërkesave nga bufferi i sistemit operativ dhe kështu minimizimin e numrit të thirrjeve sistemore.
Për benchmark-et që punojnë me të dhëna (futje, fshirje, lexim etj.), para fillimit të benchmark-ut do të krijohet (ripërtërihet) hapësira memtx, në të cilën vlerat e indeksit primar krijohen nga një gjenerator i vlerave të renditura të numrave të plotë (sequence).

DDL e hapësirës duket kështu:

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

Nëse është e nevojshme, para fillimit të benchmark-ut, hapësira plotësohet me 10,000 këtuza të këtij lloji

{id, "tuplД_"}

Qasja në këtuza bëhet përmes një vlerë të rastësishme të çelësit.

Benchmark-u përbëhet nga një kërkesë të vetme ndaj serverit, e cila ekzekutohet 10,000 herë (revolucione), të cilat, nga ana e tyre, ekzekutohen në iteracione. Iteracionet përsëriten derisa të gjitha devijimet në kohë mes 5 iteracioneve të jenë brenda tolerancës së lejuar prej 3%*. Pas kësaj rezultati mesatar merret. Ndërmjet iteracioneve është një pauzë prej 1 sekonde, për të mos lejuar që procesori të kalojë në throttling. Grumbulluesi i mbeturinave Lua është deaktivizuar para çdo iteracioni dhe aktivizohet me detyrim pas përfundimit të saj. Procesi PHP niset vetëm me zgjerimet e nevojshme për benchmark, me aktivizimin e bufferizimit të daljes dhe deaktivizimin e grumbulluesit të mbeturinave.

* Numri i revolucionave, iteracioneve dhe kufiri i tolerancës mund të ndryshohen në parametrit e benchmark-ut.

Mjedisi i testimitRezultatet e publikuara mĂ« poshtĂ« janĂ« bĂ«rĂ« nĂ« MacBookPro (2015), sistemi operativ – Fedora 30 (versioni i bĂ«rthamĂ«s 5.3.8-200.fc30.x86_64). Tarantool Ă«shtĂ« drejtuar nĂ« docker me parametrin ".

--network host"

Versionet e paketave:
Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, build a872fc2f86
PHP: 7.3.11 (cli) (ndërtuar: 22 Tetor 2019 08:11:04)
tarantool/client: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ patch për 7.3)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12

* ext-parallel: 1.1.3 patch.

Rezultatet

Mënyra sinkrone

Protokolli i Tarantool-it pĂ«rdor formatin binar MessagePack pĂ«r serializimin e mesazheve. NĂ« konektorin PECL, serializimi Ă«shtĂ« fshehur thellĂ« nĂ« brendĂ«si tĂ« bibliotekĂ«s dhe nuk Ă«shtĂ« e mundur tĂ« ndikosh nĂ« procesin e kodimit nga kodi i pĂ«rdoruesit nuk Ă«shtĂ« e mundur. Konnektori nĂ« PHP tĂ« pastĂ«r, nga ana tjetĂ«r, ofron mundĂ«sinĂ« pĂ«r tĂ« personalizuar procesin e kodifikimit duke zgjeruar koduesin standard ose duke pĂ«rdorur implementimin tuaj. Nga kutia janĂ« nĂ« dispozicion dy kodues, njĂ«ri i bazuar nĂ« msgpack/msgpack-php (zgjatja zyrtare e MessagePack PECL), tjetri — nĂ« rybakit/msgpack (nĂ« PHP tĂ« pastĂ«r).

Para se të krahasojmë konnektorët, le të masim performancën e koduesve të MessagePack për konnektorin PHP dhe në testet e mëtejshme do të përdorim atë, i cili do të tregojë rezultatin më të mirë:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Megjithëse versioni PHP (Përzier) është më i ngadalshëm se zgjatja PECL, në projekte reale megjithatë do t'ju rekomandoja të përdorni rybakit/msgpack, sepse në zgjatjen zyrtare të MessagePack, specifikimi i formatit është implementuar vetëm pjesërisht (për shembull, nuk ka mbështetje për lloje të dhënash të personalizuara, pa të cilat nuk mund të përdorni Decimal - lloji i ri i të dhënave, i prezantuar në Tarantool 2.3) dhe ka një sërë çështjesh të tjera problemeve (duke përfshirë probleme të kompatibilitetit me PHP 7.4). Dhe në përgjithësi, projekti duket se është braktisur.

Pra, le të masim performancën e konnektorëve në modin sinkron:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Siç duket nga grafiku, konnektori PECL (Tarantool) tregon njĂ« performancĂ« mĂ« tĂ« mirĂ« nĂ« krahasim me konnektorin nĂ« PHP (Client). Por kjo nuk Ă«shtĂ« befasuese, duke pasur parasysh se ky i fundit, pĂ«rveç se Ă«shtĂ« implementuar nĂ« njĂ« gjuhĂ« mĂ« tĂ« ngadalshme, kryen gjithashtu mĂ« shumĂ« punĂ«: nĂ« çdo thirrje krijohet njĂ« objekt i ri KĂ«rkesa dhe PĂ«rgjigje (nĂ« rastin e Select — madje edhe Kriteret, dhe nĂ« rastin e Update/Upsert — Operacioneve), entitete tĂ« veçanta Connection, Packer dhe Handler shtojnĂ« gjithashtu overhead. ËshtĂ« e qartĂ« qĂ« pĂ«r fleksibilitetin duhet tĂ« paguash. MegjithatĂ«, nĂ« pĂ«rgjithĂ«si, interpretuese PHP tregon njĂ« performancĂ« tĂ« mirĂ«, edhe pse diferenca Ă«shtĂ« aty, por ajo Ă«shtĂ« e vogĂ«l dhe mund tĂ« bĂ«het edhe mĂ« e vogĂ«l me pĂ«rdorimin e preload nĂ« PHP 7.4, pa folur pĂ«r JIT nĂ« PHP 8.

Le të vazhdojmë. Në Tarantool 2.0 ka ardhur mbështetje për SQL. Le të provojmë të kryejmë operacione Select, Insert, Update dhe Delete duke përdorur protokollin SQL dhe të krahasojmë rezultatet me ekuivalentët noSQL (binare):

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Rezultatet e SQL nuk janë shumë impresionuese (mosharoni se ende jemi duke testuar modin sinkron). Megjithatë, nuk do të shqetësohesha për këtë para kohe, mbështetja për SQL është ende në zhvillim aktiv (relativisht së fundmi, për shembull, është shtuar mbështetja për deklaratat e përgatitura) dhe, duke parë listën issues, motorin SQL e presin disa optimizime në të ardhmen.

Async

Tani le të shohim se si zgjatja Async mund të na ndihmojë për të përmirësuar rezultatet më sipër. Për të shkruar aplikacione asinkrone, zgjatja ofron një API të bazuar në korutina, dhe ne do ta përdorim atë. Duke eksperimentuar, zbulojmë se numri optimal i korutinave për mjedisin tonë është 25:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
“E shpĂ«rndajmĂ«â€ 10,000 operacione nĂ« 25 korutina dhe shohim se çfarĂ« rezultati kemi:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Numri i operacioneve në sekondë u rrit më shumë se tri herë për tarantool-php/client!

Fatkeqësisht, konnektori PECL nuk u aktivizua me ext-async.

Por si është me SQL?

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Siç e shihni, në modin asinkron diferenca midis protokollit binar dhe SQL u ul brenda kufijve të gabimit.

tĂ« drejtuar asinkron, paralel dhe asinkron-paralel. 🙂 Gjithashtu, nuk duam tĂ« prekim kodin e vetĂ« konektorĂ«ve. Aktualisht ekzistojnĂ« disa zgjerime qĂ« lejojnĂ« arritjen e dĂ«shiruar:

Përsëri zbulojmë numrin optimal të korutinave, tani për Swoole:
Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Do të ndalemi në 25. Të njëjtin trik, që me zgjatjen Async, e përsërisim - shpërndajmë 10,000 operacione midis 25 korutina. Përveç kësaj, do të shtojmë një provë tjetër, në të cilën do të ndajnë të gjithë punën në 2 procese (dmth çdo proces do të kryejë 5,000 operacione në 25 korutina). Proceset do të krijohen përmes SwooleProcess.

Rezultatet:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Swole tregon një rezultat disi më të ulët në krahasim me Async kur ekzekutohet në një proces, por me 2 procese, situata ndryshon ndjeshëm (numri 2 është zgjedhur jo rastësisht, në makinën time pikërisht 2 procese treguan rezultatin më të mirë).

Për më tepër, në zgjatjen Async gjithashtu ka API për punuar me procese, megjithatë nuk kam vënë re ndonjë ndryshim nga ekzekutimi i benchmarkeve në një apo disa procese (nuk përjashtohet se diku kam bërë një gabim).

SQL vs protokolli binar:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Ashtu si me Async, diferenca midis operacioneve binar dhe SQL u zhduk në mënyrë asinkrone.

async.tcp = 1

Duke qenë se zgjatja Paralele nuk lidhet me korutina, por me procese, do të masim numrin optimal të proceseve paralele:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Ai është 16 në makinën time. Le të ekzekutojmë benchmarket e konnektorëve në 16 procese paralele:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Siç e shihni, rezultati është edhe më i mirë se me zgjatjet asinkrone (përveç Swoole të aktivizuar në 2 procese). Vini re se për konnektorin PECL, në vendin e operacioneve Update dhe Upsert, është bosh. Kjo është për shkak se këto operacione dështuan me një gabim - nuk di nëse është faj i ext-parallel, ext-tarantool apo i të dyjave.

Tani le të krahasojmë performancën e SQL:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel
Vini re ngjashmërinë me grafikun për konnektorët që u aktivizuan sinkronikisht?

E gjithë kjo

Në fund, le të sintetizojmë të gjitha rezultatet në një grafik, për të parë pamjen e përgjithshme të zgjatjeve që po testojmë. Do të shtojmë në grafik vetëm një test të ri, që ende nuk e kemi bërë - do të nisnim korutinat Async paralelisht duke përdorur Parallel*. Ideja e integrimit të zgjatjeve të përmendura më sipër është diskutuar nga autorët, megjithatë nuk është arritur një konsensus, do të duhet ta bëjmë këtë vetë.

* Nuk arritëm të nisim korutinat Swoole me Parallel, duket se këto zgjatje janë të papajtueshme.

Prandaj, rezultatet përfundimtare:

Po përshpejtojmë lidhësit PHP për Tarantool me ndihmën e Async, Swoole dhe Parallel

Në vend të përfundimit

Mendimi im Ă«shtĂ« se rezultatet janĂ« mjaft tĂ« kĂ«naqshme, dhe ndjej se kjo nuk Ă«shtĂ« akoma kufiri! NĂ«se do t'ju nevojitej kjo nĂ« njĂ« projekt real, e vendosni vetĂ«m ju, unĂ« do tĂ« thosha se pĂ«r mua ky ishte njĂ« eksperiment interesant, qĂ« lejon vlerĂ«simin e asaj çfarĂ« mund tĂ« ‘shpĂ«rndahen’ nga njĂ« lidhje TCP sinkron me pĂ«rpjekje minimale. NĂ«se keni ide pĂ«r pĂ«rmirĂ«simin e benchmark-Ă«ve - do tĂ« pranoni me kĂ«naqĂ«si kĂ«rkesĂ«n tuaj pĂ«r bashkĂ«punim. I gjithĂ« kodi me udhĂ«zime pĂ«r nisje dhe rezultatet Ă«shtĂ« publikuar nĂ« njĂ« repozitorit.

Burimi: habr.com

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster