Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel

V ekosistemu PHP trenutno obstajata dva konektorja za delo s strežnikom Tarantool - to je uradna razširitev PECL tarantool/tarantool-php, napisano v C, in tarantool-php/odjemalec, napisano v PHP. Sem avtor slednjega.

V tem članku bi rad delil rezultate testiranja zmogljivosti obeh knjižnic in pokazal, kako lahko z minimalnimi spremembami kode dosežete 3-5 povečanje zmogljivosti (na sintetičnih testih!).

Kaj bomo testirali?

Preizkusili bomo zgoraj omenjene sinhrono konektorji, ki tečejo asinhrono, vzporedno in asinhrono vzporedno. 🙂 Prav tako se ne želimo dotikati kode samih konektorjev. Trenutno je na voljo več razširitev, s katerimi lahko dosežete, kar želite:

  • Swoole ― visoko zmogljivo asinhrono ogrodje za PHP. Uporabljajo ga internetni velikani, kot sta Alibaba in Baidu. Od različice 4.1.0 se je pojavila čarobna metoda SwooleRuntime::enableCoroutine(), ki vam omogoča "pretvorbo sinhronih omrežnih knjižnic PHP v asinhrone z eno vrstico kode."
  • Async je bil do nedavnega zelo obetavna razširitev za asinhrono delo v PHP. Zakaj do nedavnega? Na žalost je avtor iz meni neznanega razloga izbrisal repozitorij in nadaljnja usoda projekta ni jasna. Moral ga bom uporabiti ena iz vilic. Tako kot Swoole vam tudi ta razširitev omogoča, da si enostavno nadenete hlače z enim zamahom zapestja, da omogočite asinhronost z zamenjavo standardne izvedbe tokov TCP in TLS z njihovimi asinhronimi različicami. To se naredi z možnostjo "async.tcp = 1".
  • vzporedno ― dokaj nova razširitev znanega Joeja Watkinsa, avtorja knjižnic, kot so phpdbg, apcu, pthreads, pcov, uopz. Razširitev ponuja API za večnitnost v PHP in je postavljena kot zamenjava za pthreads. Pomembna omejitev knjižnice je, da deluje le z različico PHP ZTS (Zend Thread Safe).

Kako bomo testirali?

Zaženimo primerek Tarantoola z onemogočenim beleženjem vnaprej (wal_mode = nič) in povečan omrežni medpomnilnik (branje vnaprej = 1 * 1024 * 1024). Prva možnost bo odpravila delo z diskom, druga pa bo omogočila branje več zahtev iz medpomnilnika operacijskega sistema in s tem zmanjšala število sistemskih klicev.

Pri merilih uspešnosti, ki delujejo s podatki (vstavljanje, brisanje, branje itd.), bo pred zagonom merila uspešnosti (ponovno) ustvarjen prostor memtx, v katerem so vrednosti primarnega indeksa ustvarjene z generatorjem urejenih celih vrednosti ​(zaporedje).
Prostorski DDL izgleda takole:

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

Po potrebi se pred zagonom primerjalnega testa prostor zapolni z 10,000 tulpmi oblike

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

Do torkov se dostopa z uporabo naključne vrednosti ključa.

Sam merilo uspešnosti je ena zahteva strežniku, ki se izvede 10,000-krat (obratov), ​​ti pa se izvajajo v iteracijah. Iteracije se ponavljajo, dokler niso vsa časovna odstopanja med 5 iteracijami znotraj sprejemljive napake 3 %*. Po tem se vzame povprečni rezultat. Med ponovitvami je 1-sekundni premor, da se prepreči dušenje procesorja. Luin zbiralnik smeti je onemogočen pred vsako ponovitvijo in se mora zagnati, ko se zaključi. Proces PHP se zažene samo z razširitvami, potrebnimi za primerjalno vrednost, z omogočenim medpomnilnikom izhoda in onemogočenim zbiralnikom smeti.

* Število vrtljajev, ponovitev in prag napake je mogoče spremeniti v nastavitvah primerjalnih vrednosti.

Testno okolje

Spodaj objavljeni rezultati so bili narejeni na MacBookPro (2015), operacijski sistem - Fedora 30 (verzija jedra 5.3.8-200.fc30.x86_64). Tarantool je bil zagnan v dockerju s parametrom "--network host".

Različice paketov:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, zgradba a872fc2f86
PHP: 7.3.11 (cli) (zgrajeno: 22. oktober 2019 08:11:04)
tarantool/odjemalec: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ popravek za 7.3)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12
zunanja vzporednica: 1.1.3

* Na žalost uradni konektor ne deluje z različico PHP > 7.2. Za prevajanje in zagon razširitve na PHP 7.3 sem moral uporabiti obliž.

Ugotovitve

Sinhroni način

Protokol Tarantool uporablja binarno obliko MessagePack za serializacijo sporočil. V konektorju PECL je serializacija skrita globoko v globinah knjižnice in vpliva na proces kodiranja iz uporabniške kode se ne zdi mogoče. Nasprotno, čisti priključek PHP nudi možnost prilagajanja postopka kodiranja z razširitvijo standardnega kodirnika ali z uporabo lastne izvedbe. Na voljo sta dva kodirnika, eden temelji na msgpack/msgpack-php (uradna razširitev MessagePack PECL), drugi je vklopljen rybakit/msgpack (v čistem PHP).

Pred primerjavo konektorjev bomo izmerili zmogljivost kodirnikov MessagePack za PHP konektor in v nadaljnjih testih uporabili tistega, ki bo pokazal najboljši rezultat:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Čeprav je različica PHP (Pure) po hitrosti slabša od razširitve PECL, bi jo v resničnih projektih še vedno priporočal. rybakit/msgpack, ker je v uradni razširitvi MessagePack specifikacija formata implementirana le delno (na primer, ni podpore za podatkovne tipe po meri, brez katerih ne boste mogli uporabljati Decimal - novega podatkovnega tipa, predstavljenega v Tarantool 2.3) in ima število drugih težave (vključno s težavami z združljivostjo s PHP 7.4). No, na splošno je projekt videti zapuščen.

Torej, izmerimo zmogljivost konektorjev v sinhronem načinu:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Kot je razvidno iz grafa, PECL konektor (Tarantool) kaže boljšo zmogljivost v primerjavi s PHP konektorjem (Client). A to ni presenetljivo, glede na to, da slednji poleg tega, da je implementiran v počasnejšem jeziku, dejansko opravi več dela: z vsakim klicem se ustvari nov objekt Zahteva и odgovor (v primeru Select - tudi Merila, in v primeru Posodobi/Upsert ― operacije), ločene entitete povezava, Packer и Handler dodajo tudi režijske stroške. Očitno ima prilagodljivost svojo ceno. Vendar na splošno tolmač PHP kaže dobro zmogljivost, čeprav obstaja razlika, je nepomembna in morda bo še manjša pri uporabi prednalaganja v PHP 7.4, da ne omenjam JIT v PHP 8.

Gremo naprej. Tarantool 2.0 je dodal podporo za SQL. Poskusimo izvesti operacije Select, Insert, Update in Delete z uporabo protokola SQL in primerjamo rezultate z ekvivalenti noSQL (binarni):

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Rezultati SQL niso zelo impresivni (naj vas spomnim, da še vedno preizkušamo sinhroni način). Vendar se zaradi tega ne bi razburjal pred časom; podpora za SQL je še vedno v aktivnem razvoju (razmeroma nedavno je bila na primer dodana podpora pripravljene izjave) in sodeč po seznamu Vprašanja, bo mehanizem SQL v prihodnosti deležen številnih optimizacij.

Asinh

No, zdaj pa poglejmo, kako nam lahko razširitev Async pomaga izboljšati zgornje rezultate. Za pisanje asinhronih programov razširitev ponuja API, ki temelji na korutinah, ki jih bomo uporabili. Empirično ugotovimo, da je optimalno število korutin za naše okolje 25:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
»Razporedite« 10,000 operacij na 25 korutin in poglejte, kaj se zgodi:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Število operacij na sekundo se je povečalo za več kot 3-krat tarantool-php/odjemalec!

Na žalost se konektor PECL ni začel z ext-async.

Kaj pa SQL?

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Kot lahko vidite, je v asinhronem načinu razlika med binarnim protokolom in SQL postala znotraj meje napake.

Swoole

Spet ugotovimo optimalno število korutin, tokrat za Swoole:
Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Ustavimo se pri 25. Ponovimo isti trik kot pri razširitvi Async – 10,000 operacij porazdelimo med 25 korutin. Poleg tega bomo dodali še en test, v katerem bomo celotno delo razdelili na 2 dva procesa (to pomeni, da bo vsak proces izvedel 5,000 operacij v 25 korutinah). Procesi bodo ustvarjeni z uporabo SwooleProcess.

Rezultati:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Swole kaže nekoliko nižji rezultat v primerjavi z Async, ko se izvaja v enem procesu, vendar se pri 2 procesih slika dramatično spremeni (številka 2 ni bila izbrana po naključju; na mojem računalniku sta 2 procesa pokazala najboljši rezultat).

Mimogrede, razširitev Async ima tudi API za delo s procesi, vendar tam nisem opazil nobene razlike od izvajanja meril uspešnosti v enem ali več procesih (možno je, da sem kje zamočil).

SQL proti binarnemu protokolu:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Kot pri Async je razlika med binarnimi operacijami in operacijami SQL odpravljena v asinhronem načinu.

vzporedno

Ker pri razširitvi Parallel ne gre za korutine, ampak za niti, izmerimo optimalno število vzporednih niti:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Na mojem stroju je 16. Zaženimo merila uspešnosti konektorja na 16 vzporednih nitih:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Kot lahko vidite, je rezultat celo boljši kot pri asinhronih razširitvah (če ne štejemo Swoole, ki teče na 2 procesih). Upoštevajte, da sta za konektor PECL operaciji Update in Upsert prazni. To je posledica dejstva, da te operacije niso uspele z napako - ne vem, ali je bila napaka ext-parallel, ext-tarantool ali oboje.

Zdaj pa primerjajmo zmogljivost SQL:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel
Ste opazili podobnost z grafom za konektorje, ki delujejo sinhrono?

Skupaj

In končno, povzamemo vse rezultate v enem grafu, da vidimo celotno sliko za preizkušene razširitve. Dodajmo samo en nov test na grafikon, ki ga še nismo naredili – vzporedno zaženimo korutine Async z uporabo Parallel*. Zamisel o integraciji zgornjih razširitev že obstaja se je razpravljalo avtorjev, vendar soglasja niso dosegli, boste morali narediti sami.

* S programom Parallel ni bilo mogoče zagnati korutin Swoole; zdi se, da te razširitve niso združljive.

Torej, končni rezultati:

Pospeševanje konektorjev PHP za Tarantool z uporabo Async, Swoole in Parallel

Namesto zaključka

Po mojem mnenju so se rezultati izkazali za precej vredne in iz nekega razloga sem prepričan, da to ni meja! Ne glede na to, ali se morate o tem odločiti v resničnem projektu samo zase, bom rekel le, da je bil zame zanimiv eksperiment, ki vam omogoča, da ocenite, koliko lahko z minimalnim naporom "iztisnete" iz sinhronega TCP priključka. Če imate ideje za izboljšanje primerjalnih vrednosti, bom z veseljem upošteval vašo zahtevo po vleki. Vsa koda z navodili za zagon in rezultati je objavljena ločeno repozitorije.

Vir: www.habr.com

Dodaj komentar