
Aktualisht, nĂ« ekosistemin PHP ekzistojnĂ« dy konektorĂ« pĂ«r punĂ« me serverin Tarantool â zgjerimi zyrtar PECL , i shkruar nĂ« C, dhe , i shkruar nĂ« PHP. UnĂ« jam autori i kĂ«tij tĂ« fundit.
NĂ« kĂ«tĂ« artikull dua tĂ« ndaj rezultatet e testimit tĂ« performancĂ«s sĂ« tĂ« dyja bibliotekave dhe tĂ« tregoj se si, me ndryshime minimale nĂ« kod, mund tĂ« arrihet njĂ« rritje e performancĂ«s prej 3â5 herĂ« (nĂ« teste sintetike!).
ĂfarĂ« do tĂ« testojmĂ«?
Do tĂ« testojmĂ« konektorĂ«t e pĂ«rmendur mĂ« sipĂ«r, sinkronĂ« , tĂ« ekzekutuar nĂ« mĂ«nyrĂ« asinkrone, paralelisht dhe nĂ« mĂ«nyrĂ« asinkrone-paralele. đ Gjithashtu, nuk duam tĂ« prekim kodin e vetĂ« konektorĂ«ve. Aktualisht janĂ« tĂ« disponueshme disa zgjerime qĂ« lejojnĂ« tĂ« arrihet rezultati i dĂ«shiruar:
- â njĂ« framework asinkron me performancĂ« tĂ« lartĂ« pĂ«r PHP. PĂ«rdoret nga gjigantĂ« tĂ« internetit si Alibaba dhe Baidu. QĂ« nga versioni 4.1.0 Ă«shtĂ« shfaqur metoda magjike SwooleRuntime::enableCoroutine(), e cila lejon qĂ« âme njĂ« rresht kodi, bibliotekat sinkrone tĂ« rrjetit nĂ« PHP tĂ« shndĂ«rrohen nĂ« asinkroneâ.
- Async â deri vonĂ« ishte njĂ« zgjerim mjaft premtues pĂ«r punĂ« asinkrone nĂ« PHP. Pse deri vonĂ«? FatkeqĂ«sisht, pĂ«r njĂ« arsye qĂ« nuk e di, autori e ka fshirĂ« repository-n dhe e ardhmja e projektit mbetet e paqartĂ«. Do tĂ« duhet tĂ« pĂ«rdorim nga fork-et. Ashtu si Swoole, edhe ky zgjerim lejon tĂ« aktivizohet lehtĂ«sisht asinkronia duke zĂ«vendĂ«suar implementimin standard tĂ« rrjedhave TCP dhe TLS me versionet e tyre asinkrone. Kjo bĂ«het pĂ«rmes opsionit âasync.tcp = 1«.
- â njĂ« zgjerim mjaft i ri nga Joe Watkins, i njohur si autor i bibliotekave phpdbg, apcu, pthreads, pcov, uopz. Zgjerimi ofron njĂ« API pĂ«r punĂ« shumĂ«fijĂ«she nĂ« PHP dhe pozicionohet si zĂ«vendĂ«sues i pthreads. Kufizimi i rĂ«ndĂ«sishĂ«m i kĂ«saj biblioteke Ă«shtĂ« se funksionon vetĂ«m me versionin ZTS (Zend Thread Safe) tĂ« PHP.
Si do ta testojmë?
Do të nisim një instancë të Tarantool me ditarin e regjistrimit paraprak të çaktivizuar (wal_mode = none) dhe me buffer rrjeti të rritur (readahead = 1 * 1024 * 1024). Opsioni i parë do të përjashtojë punën me diskun, ndërsa i dyti do të lejojë leximin e më shumë kërkesave nga buffer-i i sistemit operativ dhe kështu do të minimizojë numrin e thirrjeve sistemore.
Për benchmark-et që punojnë me të dhëna (shtim, fshirje, lexim etj.), para nisjes së benchmark-ut do të krijohet ose rikrijohet një memtx-space, ku vlerat e indeksit primar gjenerohen nga gjeneratori i vlerave të renditura të numrave të plotë (sequence).
DDL i space 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}})Sipas nevojës, para nisjes së benchmark-ut, space mbushet me 10,000 tuple të formës
{id, "tuplД_"}Qasja te tuple kryhet sipas një vlere të rastësishme të çelësit.
Vetë benchmark-u përfaqëson një kërkesë të vetme ndaj serverit, e cila ekzekutohet 10,000 herë (revolucione), që nga ana e tyre kryhen në iteracione. Iteracionet përsëriten derisa të gjitha devijimet kohore midis 5 iteracioneve të jenë brenda kufirit të lejuar të gabimit prej 3 %*. Pas kësaj merret rezultati mesatar. Midis iteracioneve ka një pauzë prej 1 sekonde, që procesori të mos kalojë në throttling. Garbage collector i Lua çaktivizohet para çdo iteracioni dhe niset me forcë pas përfundimit të tij. Procesi PHP niset vetëm me zgjerimet e nevojshme për benchmark-un, me output buffering të aktivizuar dhe garbage collector të çaktivizuar.
* Numri i revolucioneve, iteracioneve dhe pragu i gabimit mund të ndryshohen në cilësimet e benchmark-ut.
Mjedisi i testimit
Rezultatet e publikuara mĂ« poshtĂ« janĂ« marrĂ« nĂ« njĂ« MacBookPro (2015), me sistem operativ Fedora 30 (versioni i kernelit 5.3.8-200.fc30.x86_64). Tarantool u nis 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) (built: Oct 22 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
* Fatkeqësisht, konektori zyrtar nuk punon me versionin PHP > 7.2. Për të kompiluar dhe nisur zgjerimin në PHP 7.3, u desh të përdorej .
Rezultatet
Modaliteti sinkron
Protokolli i Tarantool përdor formatin binar për serializimin e mesazheve. Në konektorin PECL, serializimi është i fshehur thellë në brendësi të bibliotekës dhe të ndikosh në procesin e kodimit nga kodi userland . Ndryshe, konektori në PHP të pastër ofron mundësinë e personalizimit të procesit të enkodimit duke zgjeruar enkoderin standard ose duke përdorur implementimin tuaj. Si parazgjedhje janë të disponueshëm dy enkoderë: njëri bazohet në (zgjerimi zyrtar MessagePack PECL), ndërsa tjetri në (në PHP të pastër).
Para se të krahasojmë konektorët, le të masim performancën e enkoderëve MessagePack për konektorin PHP dhe në testet e mëtejshme do të përdorim atë që jep rezultatin më të mirë:

Edhe pse versioni PHP (Pure) Ă«shtĂ« mĂ« i ngadaltĂ« se zgjerimi PECL, nĂ« projekte reale unĂ« pĂ«rsĂ«ri do tĂ« rekomandoja pĂ«rdorimin e , sepse nĂ« zgjerimin zyrtar MessagePack specifikimi i formatit Ă«shtĂ« implementuar vetĂ«m pjesĂ«risht (pĂ«r shembull, nuk ka mbĂ«shtetje pĂ«r tipe tĂ« personalizuara tĂ« tĂ« dhĂ«nave, pa tĂ« cilat nuk do tĂ« mund tĂ« pĂ«rdorni Decimal â tipi i ri i tĂ« dhĂ«nave i prezantuar nĂ« Tarantool 2.3) dhe ka njĂ« sĂ«rĂ« problemesh tĂ« tjera (pĂ«rfshirĂ« problemet e pajtueshmĂ«risĂ« me PHP 7.4). Dhe nĂ« pĂ«rgjithĂ«si, projekti duket i braktisur.
Tani le të masim performancën e konektorëve në modalitetin sinkron:

Siç shihet nga grafiku, konektori PECL (Tarantool) tregon performancĂ« mĂ« tĂ« mirĂ« krahasuar me konektorin nĂ« PHP (Client). Por kjo nuk Ă«shtĂ« pĂ«r tâu habitur, duke pasur parasysh se i dyti, pĂ«rveçse Ă«shtĂ« implementuar nĂ« njĂ« gjuhĂ« mĂ« tĂ« ngadaltĂ«, nĂ« thelb kryen mĂ« shumĂ« punĂ«: nĂ« çdo thirrje krijohet njĂ« objekt i ri Request dhe PĂ«rgjigjja (nĂ« rastin e Select â edhe Criteria, ndĂ«rsa nĂ« rastin e Update/Upsert â Operations), entitetet e veçanta Connection, Packer dhe Handler gjithashtu shtojnĂ« overhead. ĂshtĂ« e qartĂ« se fleksibiliteti ka koston e vet. MegjithatĂ«, nĂ« pĂ«rgjithĂ«si, interpreteri PHP tregon performancĂ« tĂ« mirĂ«; edhe pse ka diferencĂ«, ajo Ă«shtĂ« e vogĂ«l dhe ndoshta do tĂ« jetĂ« edhe mĂ« e vogĂ«l me pĂ«rdorimin e preloading nĂ« PHP 7.4, pa pĂ«rmendur JIT nĂ« PHP 8.
Le tĂ« vazhdojmĂ«. NĂ« Tarantool 2.0 u shtua mbĂ«shtetja pĂ«r SQL. Le tĂ« provojmĂ« tĂ« kryejmĂ« operacionet Select, Insert, Update dhe Delete duke pĂ«rdorur protokollin SQL dhe tâi krahasojmĂ« rezultatet me ekuivalentĂ«t noSQL (binarĂ«):

Rezultatet e SQL nuk janë veçanërisht mbresëlënëse (ju kujtoj se ende po testojmë modalitetin sinkron). Megjithatë, nuk do të nxitoja të zhgënjehesha për këtë, sepse mbështetja për SQL është ende në zhvillim aktiv (për shembull, jo shumë kohë më parë u shtua mbështetja për ) dhe, duke gjykuar nga lista e , motori SQL më tej pret një sërë optimizimesh.
Async
Tani të shohim se si zgjerimi Async mund të na ndihmojë të përmirësojmë rezultatet e mësipërme. Për të shkruar programe asinkrone, zgjerimi ofron një API të bazuar në korutina (coroutines), dhe pikërisht atë do të përdorim. Nga testimet rezulton se numri optimal i korutinave për mjedisin tonë është 25:

I âshpĂ«rndajmĂ«â 10,000 operacione nĂ« 25 korutina dhe shohim çfarĂ« rezultati morĂ«m:

Numri i operacioneve për sekondë u rrit më shumë se 3 herë për !
Për fat të keq, konektori PECL nuk u nis me ext-async.
Po me SQL çfarë ndodh?

Siç mund ta shihni, në modalitetin asinkron diferenca midis protokollit binar dhe SQL ra brenda kufijve të devijimit statistikor.
Swoole
Përsëri po përcaktojmë numrin optimal të korutinave, këtë herë për Swoole:

Do tĂ« ndalemi te 25. Le tĂ« pĂ«rsĂ«risim tĂ« njĂ«jtin truk si me zgjerimin Async â do tĂ« shpĂ«rndajmĂ« 10,000 operacione mes 25 korutinave. PĂ«rveç kĂ«saj, do tĂ« shtojmĂ« edhe njĂ« test ku tĂ« gjithĂ« ngarkesĂ«n do ta ndajmĂ« nĂ« 2 procese (pra secili proces do tĂ« kryejĂ« 5,000 operacione nĂ« 25 korutina). Proceset do tĂ« krijohen me ndihmĂ«n e SwooleProcess.
Rezultatet:

Swoole tregon një rezultat pak më të ulët krahasuar me Async kur ekzekutohet në një proces, por me 2 procese pamja ndryshon rrënjësisht (numri 2 nuk është zgjedhur rastësisht: në kompjuterin tim pikërisht 2 procese dhanë rezultatin më të mirë).
Meqë ra fjala, zgjerimi Async ka gjithashtu API për punë me procese, por aty nuk vura re ndonjë ndryshim nga ekzekutimi i benchmark-eve në një apo disa procese (nuk përjashtohet që mund të kem bërë ndonjë gabim diku).
SQL kundrejt protokollit binar:

Ashtu si me Async, diferenca midis operacioneve binare dhe atyre SQL zbutet në modalitetin asinkron.
Parallel
Meqenëse zgjerimi Parallel nuk ka të bëjë me korutina, por me fije ekzekutimi, le të masim numrin optimal të fijeve paralele:

Në kompjuterin tim ai është 16. Le të nisim benchmark-et e konektorëve në 16 fije paralele:

Siç mund ta shihni, rezultati Ă«shtĂ« madje mĂ« i mirĂ« se me zgjerimet asinkrone (me pĂ«rjashtim tĂ« Swoole tĂ« nisur nĂ« 2 procese). Vini re se pĂ«r konektorin PECL, te operacionet Update dhe Upsert nuk ka tĂ« dhĂ«na. Kjo lidhet me faktin se kĂ«to operacione dĂ«shtuan me gabim â nuk e di nĂ«se faji Ă«shtĂ« i ext-parallel, ext-tarantool apo i tĂ« dyjave.
Tani le të krahasojmë performancën e SQL:

E vutë re ngjashmërinë me grafikun për konektorët e nisur në mënyrë sinkrone?
Gjithçka së bashku
Dhe nĂ« fund, le tâi pĂ«rmbledhim tĂ« gjitha rezultatet nĂ« njĂ« grafik tĂ« vetĂ«m, qĂ« tĂ« shohim pamjen e pĂ«rgjithshme tĂ« zgjerimeve tĂ« testuara. NĂ« grafik do tĂ« shtojmĂ« vetĂ«m njĂ« test tĂ« ri, tĂ« cilin ende nuk e kemi bĂ«rĂ« â do tâi nisim coroutine-t Async paralelisht me ndihmĂ«n e Parallel*. Ideja e integrimit tĂ« zgjerimeve tĂ« pĂ«rmendura mĂ« sipĂ«r Ă«shtĂ« nga autorĂ«t, por ende nuk Ă«shtĂ« arritur konsensus, ndaj do tĂ« na duhet ta bĂ«jmĂ« vetĂ«.
* Nuk u arrit të niseshin coroutine-t Swoole me Parallel; duket se këto zgjerime nuk janë të pajtueshme.
Pra, rezultatet përfundimtare:

Në përfundim
Sipas mendimit tim, rezultatet dolĂ«n mjaft tĂ« mira, dhe pĂ«r ndonjĂ« arsye jam i bindur se kjo nuk Ă«shtĂ« ende kufiri! NĂ«se kjo ju nevojitet nĂ« njĂ« projekt real, kĂ«tĂ« mund ta vendosni vetĂ«m ju vetĂ«; unĂ« mund tĂ« them vetĂ«m se pĂ«r mua ishte njĂ« eksperiment interesant, qĂ« bĂ«ri tĂ« mundur vlerĂ«simin se sa mund tĂ« ânxirretâ nga njĂ« konektor TCP sinkron me pĂ«rpjekje minimale. NĂ«se keni ide pĂ«r pĂ«rmirĂ«simin e benchmark-ve, do ta shqyrtoj me kĂ«naqĂ«si pull request-in tuaj. I gjithĂ« kodi me udhĂ«zimet e nisjes dhe rezultatet Ă«shtĂ« publikuar nĂ« njĂ« .
Burimi: habr.com
