Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel

U PHP ekosistemu trenutno postoje dva konektora za rad sa Tarantool serverom - ovo je zvanična PECL ekstenzija tarantool/tarantool-php, napisano u C, i tarantool-php/client, napisan u PHP-u. Ja sam autor potonjeg.

U ovom članku želim podijeliti rezultate testiranja performansi obje biblioteke i pokazati kako, uz minimalne promjene koda, možete postići povećanje performansi za 3-5 (na sintetičkim testovima!).

Šta ćemo testirati?

Mi ćemo testirati one gore navedene sinhroni konektori koji rade asinhrono, paralelno i asinhrono-paralelno. 🙂 Također ne želimo dirati kod samih konektora. Trenutno je dostupno nekoliko ekstenzija za postizanje onoga što želite:

  • Swoole ― asinhroni okvir visokih performansi za PHP. Koriste ga internet giganti kao što su Alibaba i Baidu. Od verzije 4.1.0 pojavila se magična metoda SwooleRuntime::enableCoroutine(), koji vam omogućava da "konvertujete sinhrone PHP mrežne biblioteke u asinkrone sa jednom linijom koda."
  • Async je donedavno bio vrlo obećavajuće proširenje za asinhroni rad u PHP-u. Zašto donedavno? Nažalost, iz meni nepoznatog razloga, autor je obrisao spremište i dalja sudbina projekta je nejasna. Moraću da ga iskoristim jedan od viljuški. Kao i Swoole, ovo proširenje vam omogućava da lako uključite svoje hlače pokretom ručnog zgloba kako biste omogućili asinhroniju zamjenom standardne implementacije TCP i TLS streamova njihovim asinhronim verzijama. To se radi putem opcije “async.tcp = 1".
  • Paralelno ― prilično novo proširenje poznatog Joea Watkinsa, autora biblioteka kao što su phpdbg, apcu, pthreads, pcov, uopz. Ekstenzija pruža API za višenitnost u PHP-u i pozicionirana je kao zamjena za pthreads. Značajno ograničenje biblioteke je to što radi samo sa ZTS (Zend Thread Safe) verzijom PHP-a.

Kako ćemo testirati?

Pokrenimo instancu Tarantool-a sa onemogućenim evidentiranjem unaprijed (wal_mode = nijedan) i povećan mrežni bafer (readahead = 1 * 1024 * 1024). Prva opcija će eliminirati rad s diskom, druga će omogućiti čitanje više zahtjeva iz bafera operativnog sistema i na taj način minimizirati broj sistemskih poziva.

Za benchmarkove koji rade sa podacima (umetanje, brisanje, čitanje, itd.), prije pokretanja benčmarka, (re)kreiraće se memtx prostor u kojem se primarne vrijednosti indeksa kreiraju pomoću generatora uređenih cjelobrojnih vrijednosti ​(sekvenca).
Prostor DDL izgleda ovako:

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

Ako je potrebno, prije pokretanja benčmarka, prostor se popunjava sa 10,000 tuple forme

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

Torkama se pristupa pomoću nasumične vrijednosti ključa.

Sam benčmark je jedan zahtjev prema serveru, koji se izvršava 10,000 puta (okretanja), koji se, pak, izvršavaju u iteracijama. Iteracije se ponavljaju sve dok sva vremenska odstupanja između 5 iteracija ne budu unutar prihvatljive greške od 3%*. Nakon toga se uzima prosječan rezultat. Između iteracija postoji pauza od 1 sekunde kako bi se spriječilo prigušivanje procesora. Lua-in sakupljač smeća je onemogućen prije svake iteracije i prisiljen je da se pokrene nakon što se završi. PHP proces se pokreće samo sa ekstenzijama neophodnim za benchmark, sa omogućenim baferovanjem izlaza i onemogućenim sakupljačem smeća.

* Broj okretaja, iteracija i prag greške mogu se promijeniti u postavkama benčmarka.

Testno okruženje

Rezultati objavljeni u nastavku su napravljeni na MacBookPro (2015), operativni sistem - Fedora 30 (kernel verzija 5.3.8-200.fc30.x86_64). Tarantool je pokrenut u docker-u sa parametrom "--network host".

Verzije paketa:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, build a872fc2f86
PHP: 7.3.11 (cli) (izgrađen: 22. oktobar 2019. 08:11:04)
tarantool/klijent: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ patch za 7.3)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12
ext-parallel: 1.1.3

* Nažalost, zvanični konektor ne radi sa PHP verzijom > 7.2. Za kompajliranje i pokretanje ekstenzije na PHP 7.3, morao sam koristiti patch.

Rezulʹtaty

Sinhroni način rada

Tarantool protokol koristi binarni format MessagePack za serijalizaciju poruka. U PECL konektoru, serijalizacija je skrivena duboko u dubinama biblioteke i utiče na proces kodiranja iz korisničkog koda ne izgleda moguće. Čisti PHP konektor, naprotiv, pruža mogućnost prilagođavanja procesa kodiranja proširenjem standardnog kodera ili korištenjem vlastite implementacije. Iz kutije su dostupna dva enkodera, jedan je baziran na msgpack/msgpack-php (zvanična ekstenzija MessagePack PECL), druga je uključena rybakit/msgpack (u čistom PHP-u).

Prije poređenja konektora, izmjerit ćemo performanse MessagePack kodera za PHP konektor i u daljnjim testovima koristit ćemo onaj koji pokazuje najbolji rezultat:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Iako je PHP verzija (Pure) inferiornija od PECL ekstenzije u brzini, u stvarnim projektima ipak bih preporučio da je koristite rybakit/msgpack, jer je u službenoj ekstenziji MessagePack specifikacija formata samo djelomično implementirana (na primjer, ne postoji podrška za prilagođene tipove podataka, bez kojih nećete moći koristiti Decimal - novi tip podataka uveden u Tarantool 2.3) i ima broj drugih problemi (uključujući probleme kompatibilnosti sa PHP 7.4). Pa, generalno, projekat izgleda napušteno.

Dakle, izmjerimo performanse konektora u sinhronom načinu rada:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Kao što se vidi iz grafikona, PECL konektor (Tarantool) pokazuje bolje performanse u odnosu na PHP konektor (Klijent). Ali to nije iznenađujuće, s obzirom na to da potonji, osim što je implementiran u sporiji jezik, zapravo radi više posla: svakim pozivom se kreira novi objekt zahtjev и odgovor (u slučaju Select - takođe kriteriji, au slučaju ažuriranja/upsert-a ― operacije), zasebni entiteti priključak, Packer и Handler oni takođe dodaju režijske troškove. Očigledno, fleksibilnost ima cijenu. Međutim, generalno gledano, PHP interpreter pokazuje dobre performanse, iako postoji razlika, ona je beznačajna, a možda će biti još i manja kada se koristi preloading u PHP 7.4, a da ne spominjemo JIT u PHP 8.

Idemo dalje. Tarantool 2.0 je dodao podršku za SQL. Pokušajmo izvršiti operacije odabira, umetanja, ažuriranja i brisanja koristeći SQL protokol i uporedimo rezultate sa noSQL (binarnim) ekvivalentima:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
SQL rezultati nisu baš impresivni (da vas podsjetim da još uvijek testiramo sinhroni način rada). Međutim, ne bih se uzrujavao zbog toga prije vremena, podrška za SQL je još uvijek u aktivnom razvoju (na primjer, podrška je dodana relativno nedavno pripremljene izjave) i, sudeći po spisku pitanja, SQL motor će u budućnosti biti podvrgnut brojnim optimizacijama.

async

Pa, sada da vidimo kako nam proširenje Async može pomoći da poboljšamo rezultate iznad. Za pisanje asinkronih programa, ekstenzija pruža API baziran na korutinama, koje ćemo koristiti. Empirijski saznajemo da je optimalan broj korutina za naše okruženje 25:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
“Rasporedite” 10,000 operacija u 25 korutina i pogledajte šta se dešava:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Broj operacija u sekundi povećan je za više od 3 puta za tarantool-php/client!

Nažalost, PECL konektor nije započeo s ext-async.

Šta je sa SQL-om?

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Kao što možete vidjeti, u asinkronom načinu rada razlika između binarnog protokola i SQL-a je bila unutar granice greške.

Swoole

Opet saznajemo optimalan broj korutina, ovaj put za Swoole:
Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Zaustavimo se na 25. Ponovimo isti trik kao sa ekstenzijom Async - rasporedite 10,000 operacija između 25 korutina. Dodatno ćemo dodati još jedan test u kojem ćemo sav rad podijeliti na 2 dva procesa (tj. svaki proces će izvesti 5,000 operacija u 25 korutina). Procesi će se kreirati pomoću SwooleProcess.

Rezultati:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Swole pokazuje nešto niži rezultat u odnosu na Async kada se pokrene u jednom procesu, ali sa 2 procesa slika se dramatično mijenja (broj 2 nije slučajno izabran; na mojoj mašini su 2 procesa pokazala najbolji rezultat).

Inače, ekstenzija Async takođe ima API za rad sa procesima, ali tu nisam primetio nikakvu razliku od pokretanja benchmarka u jednom ili više procesa (moguće je da sam negde zabrljao).

SQL vs binarni protokol:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Kao i kod Async, razlika između binarnih i SQL operacija je eliminisana u asinkronom režimu.

Paralelno

Budući da se paralelna ekstenzija ne odnosi na korutine, već na niti, izmjerimo optimalan broj paralelnih niti:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Na mojoj mašini je 16. Pokrenimo testove konektora na 16 paralelnih niti:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Kao što vidite, rezultat je čak i bolji nego kod asinhronih ekstenzija (ne računajući Swoole koji radi na 2 procesa). Imajte na umu da su za PECL konektor operacije ažuriranja i upsert prazne. To je zbog činjenice da ove operacije nisu uspjele s greškom - ne znam da li je to bila greška ext-parallel, ext-tarantool ili oboje.

Sada uporedimo SQL performanse:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel
Primećujete sličnost sa grafom za konektore koji rade sinhrono?

Zajedno

I na kraju, sažmimo sve rezultate u jedan grafikon da vidimo ukupnu sliku za testirane ekstenzije. Dodajmo samo jedan novi test na grafikon, koji još nismo uradili - paralelno ćemo pokrenuti async korutine koristeći Parallel*. Ideja o integraciji gore navedenih ekstenzija već postoji diskutovano autora, ali nije postignut konsenzus, morat ćete to sami.

* Nije bilo moguće pokrenuti Swoole korutine sa Paralelom, čini se da su ove ekstenzije nekompatibilne.

Dakle, konačni rezultati:

Ubrzanje PHP konektora za Tarantool koristeći Async, Swoole i Parallel

Umjesto zaključka

Po mom mišljenju, rezultati su se pokazali sasvim vrijedni, i iz nekog razloga sam siguran da to nije granica! Bez obzira da li o ovome trebate odlučiti u stvarnom projektu isključivo za sebe, samo ću reći da je za mene to bio zanimljiv eksperiment koji vam omogućava da procijenite koliko možete "iscijediti" iz sinkronog TCP konektora uz minimalan napor. Ako imate ideje za poboljšanje mjerila, rado ću razmotriti vaš zahtjev za povlačenjem. Sav kod sa instrukcijama za pokretanje i rezultatima objavljen je u posebnom spremišta.

izvor: www.habr.com

Dodajte komentar