Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel

I PHP-ekosystemet finns det för nÀrvarande tvÄ kopplingar för att arbeta med Tarantool-servern - det officiella PECL-tillÀgget tarantool/tarantool-php, skrivet i C, och tarantool-php/client, skrivet i PHP. Jag Àr författaren till det sistnÀmnda.

I den hÀr artikeln tÀnkte jag dela resultaten av prestandatestningen av bÄda biblioteken och visa hur man med minimala kodÀndringar kan uppnÄ en prestandaökning pÄ 3-5i syntetiska tester!).

Vad ska vi testa?

Vi kommer att testa de ovan nĂ€mnda synkrona kopplingarna, körda asynkront, parallellt och asynkront-parallellt. 🙂 Vi vill ocksĂ„ undvika att röra kopplingarnas kod. För nĂ€rvarande finns det flera tillĂ€gg som gör det möjligt att uppnĂ„ önskat resultat:

  • Swoole – en högpresterande asynkron ramverk för PHP. AnvĂ€nds av internetjĂ€ttar som Alibaba och Baidu. FrĂ„n version 4.1.0 finns det en magisk metod SwooleRuntime::enableCoroutine(), som möjliggör 'att med en rad kod omvandla synkrona nĂ€tverksbibliotek i PHP till asynkrona'.
  • Async – ett lovande tillĂ€gg för asynkron drift i PHP som fram till nyligen var populĂ€rt. Varför fram till nyligen? TyvĂ€rr har författaren av okĂ€nda skĂ€l tagit bort arkivet och projektets framtid Ă€r osĂ€ker. Vi fĂ„r anvĂ€nda ett av forkarna. Precis som Swoole gör detta tillĂ€gg det enkelt att implementera asynkronitet genom att ersĂ€tta den standardiserade TCP- och TLS-implementeringen med deras asynkrona versioner. Det görs genom alternativet 'async.tcp = 1«.
  • Parallel – ett ganska nytt tillĂ€gg frĂ„n den vĂ€lkĂ€nda Joe Watkins, skaparen av bibliotek som phpdbg, apcu, pthreads, pcov, uopz. TillĂ€gget tillhandahĂ„ller ett API för flertrĂ„dad drift i PHP och marknadsförs som en ersĂ€ttning för pthreads. Ett betydande begrĂ€nsning av biblioteket Ă€r att det endast fungerar med ZTS (Zend Thread Safe) versionen av PHP.

Hur ska vi testa?

Vi kommer att köra en Tarantool-instans med logg över förhandsinspelning avstÀngd (wal_mode = none) och en ökad nÀtverksbuffer (readahead = 1 * 1024 * 1024). Det första alternativet eliminerar diskÄtkomst, det andra ger möjlighet att lÀsa fler förfrÄgningar frÄn operativsystemets buffer och dÀrmed minimera antalet systemanrop.

För benchmarktester som arbetar med data (infogning, borttagning, lÀsning osv.) kommer en memtx-space att (Äter)skapas innan testet startar, dÀr vÀrdena för den primÀra indexen skapas av en generator för ordnade heltalsvÀrden (sequence).
DDL-space ser ut sÄ hÀr:

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

Vid behov, innan benchmarktestet startar, fylls spacet med 10 000 tupler av typen

{id, "tuple_"}

Åtkomst till tuplerna sker med ett slumpmĂ€ssigt vĂ€rde av nyckeln.

SjÀlva benchmarktestet bestÄr av en enskild begÀran till servern, som utförs 10 000 gÄnger (varv), vilket i sin tur utförs i iterationer. Iterationerna upprepas tills alla avvikelser i tiden mellan 5 iterationer Àr inom en acceptabel felmarginal pÄ 3 %*. Efter det tas ett genomsnittligt resultat. Mellan iterationerna Àr det en paus pÄ 1 sekund för att förhindra att processorn gÄr in i throttling. Lua-skrÀpunsamlaren stÀngs av före varje iteration och tvingas att starta efter dess avslutande. PHP-processen startas endast med de nödvÀndiga för benchmarktestet förlÀngningarna, med utdata-puffring aktiverad och skrÀpunsamlaren avstÀngd.

* Antalet varv, iterationer och felgrÀnser kan Àndras i instÀllningarna för benchmarktestet.

Testmiljö

De publicerade resultaten nedan uppnĂ„ddes pĂ„ en MacBookPro (2015), operativsystemet Ă€r Fedora 30 (kernelversion 5.3.8-200.fc30.x86_64). Tarantool kördes i Docker med parametern ‘--network host".

Paketversioner:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, build a872fc2f86
PHP: 7.3.11 (cli) (byggd: 22 okt 2019 08:11:04)
tarantool/client: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ patch för 7.3)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12
ext-parallel: 1.1.3

* TyvÀrr fungerar den officiella kopplingen inte med PHP-versioner > 7.2. För att kompilera och köra tillÀgget pÄ PHP 7.3 var jag tvungen att anvÀnda patchen.

Resultat

Synkront lÀge

Tarantool-protokollet anvÀnder ett binÀrt format MessagePack för serialisering av meddelanden. I PECL-kopplingen Àr serialiseringen djupt gömd i bibliotekets inre och det Àr inte möjligt att pÄverka kodningsprocessen frÄn userland-kod inte Àr möjligt.. En ren PHP-connector ger Ä sin sida möjlighet att anpassa kodningsprocessen antingen genom att utvidga standardkodaren eller genom att anvÀnda sin egen implementering. TvÄ kodare finns tillgÀngliga frÄn början, en baserad pÄ msgpack/msgpack-php (den officiella MessagePack PECL-tillÀgget), den andra pÄ rybakit/msgpack (ren PHP).

Innan vi jÀmför connectorn, lÄt oss mÀta prestandan hos MessagePack-kodare för PHP-connectorn och i de kommande testerna kommer vi anvÀnda den som visar det bÀsta resultatet:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Trots att PHP-versionen (Pure) Ă€r lĂ„ngsammare Ă€n PECL-tillĂ€gget, skulle jag fortfarande rekommendera att anvĂ€nda just rybakit/msgpack, eftersom det officiella MessagePack-tillĂ€gget endast delvis implementerat formatets specifikation (till exempel finns inget stöd för anvĂ€ndardefinierade datatyper, vilket gör att du inte kan anvĂ€nda Decimal – en ny datatyp som introducerades i Tarantool 2.3) och har en rad andra av problem (inklusive kompatibilitetsproblem med PHP 7.4). Dessutom ser projektet i allmĂ€nhet övergivet ut.

SÄ, lÄt oss mÀta prestandan hos connectorn i synkront lÀge:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Som man kan se frĂ„n diagrammet visar PECL-connectorn (Tarantool) bĂ€ttre prestanda jĂ€mfört med PHP-connectorn (Client). Men detta Ă€r inte förvĂ„nande, med tanke pĂ„ att den senare, förutom att den Ă€r implementerad i ett lĂ„ngsammare sprĂ„k, gör mer arbete: vid varje anrop skapas ett nytt objekt BegĂ€ran och Response (i fallet Select – Ă€ven Criteria, och i fallet Update/Upsert – Operations), separata entiteter Connection, Packer och Handler tillför ocksĂ„ overhead. Det Ă€r uppenbart att man fĂ„r betala för flexibiliteten. Men generellt visar PHP-tolken bra prestanda, Ă€ven om det finns en skillnad, men den Ă€r obetydlig och kommer sannolikt att bli Ă€nnu mindre vid anvĂ€ndning av preloading i PHP 7.4, för att inte tala om JIT i PHP 8.

LÄt oss gÄ vidare. I Tarantool 2.0 introducerades stöd för SQL. LÄt oss försöka utföra operationerna Select, Insert, Update och Delete med hjÀlp av SQL-protokollet och jÀmföra resultaten med noSQL (binÀra) motsvarigheter:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Resultaten frÄn SQL imponerar inte sÄ mycket (jag pÄminner om att vi fortfarande testar det synkrona lÀget). Men jag skulle inte oroa mig för detta i förtid, stöd för SQL Àr fortfarande under aktiv utveckling (relativt nyligen, till exempel, lades stöd för prepared statements) till, och judging efter listan issues, SQL-motorn vÀntar pÄ en rad optimeringar.

Async

LÄt oss nu se hur Async-tillÀgget kan hjÀlpa oss att förbÀttra resultaten ovan. För att skriva asynkrona program erbjuder tillÀgget ett API baserat pÄ korutiner (coroutines), som vi kommer att anvÀnda. Genom försök har vi kommit fram till att det optimala antalet korutiner för vÄr miljö Àr 25:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Vi "sprider ut" 10,000 operationer över 25 korutiner och ser vad resultatet blev:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Antalet operationer per sekund ökade mer Àn tre gÄnger för tarantool-php/client!

TyvÀrr startade inte PECL-anslutningen med ext-async.

Hur stÄr det till med SQL?

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Som ni ser, i asynkront lÀge Àr skillnaden mellan det binÀra protokollet och SQL inom felmarginalen.

Swoole

Vi undersöker Äter det optimala antalet korutiner, nu för Swoole:
Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Vi stannar vid 25. Vi upprepar samma trick som med Async-tillĂ€gget – sprider 10,000 operationer mellan 25 korutiner. Dessutom lĂ€gger vi till ett test dĂ€r vi delar hela arbetet pĂ„ 2 processer (det vill sĂ€ga varje process kommer att utföra 5,000 operationer i 25 korutiner). Processerna kommer att skapas med hjĂ€lp av SwooleProcess.

Resultat:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Swoole visar nÄgot lÀgre resultat jÀmfört med Async vid körning i en process, men med 2 processer förÀndras bilden radikalt (siffran 2 valdes inte av en slump, pÄ min maskin visade just 2 processer det bÀsta resultatet).

För övrigt har Async-tillÀgget ocksÄ ett API för att arbeta med processer, men jag har inte mÀrkt nÄgon skillnad mellan att köra benchmarktester i en eller flera processer (det Àr möjligt att jag kan ha gjort ett misstag nÄgonstans).

SQL mot det binÀra protokollet:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Precis som med Async, jÀmnas skillnaden mellan binÀra och SQL-operationer ut i asynkront lÀge.

Parallel

Eftersom Parallel-tillÀgget inte handlar om korutiner utan om trÄdar, mÀter vi det optimala antalet parallella trÄdar:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Det Àr 16 pÄ min maskin. LÄt oss köra benchmarktester pÄ anslutningarna med 16 parallella trÄdar:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Som ni ser, Ă€r resultatet till och med bĂ€ttre Ă€n med de asynkrona tillĂ€ggen (förutom Swoole som kördes pĂ„ 2 processer). Observera att för PECL-anslutningen Ă€r fĂ€ltet för Update och Upsert-operationer tomt. Detta beror pĂ„ att dessa operationer misslyckades med ett fel – jag vet inte om det beror pĂ„ ext-parallel, ext-tarantool eller bĂ„da.

Nu jÀmför vi SQL-prestanda:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel
Ser ni likheten med grafen för anslutningar som kördes synkront?

Allt tillsammans

Till sist, lĂ„t oss sammanstĂ€lla alla resultat i en graf för att se den övergripande bilden för de testade tillĂ€ggen. Vi lĂ€gger till ett nytt test pĂ„ grafen, som vi inte har gjort tidigare – vi kör Async-koroutiner parallellt med hjĂ€lp av Parallel*. IdĂ©n om att integrera de nĂ€mnda tillĂ€ggen har redan diskuterats av författarna, men nĂ„gon konsensus har Ă€nnu inte nĂ„tts. Vi fĂ„r göra detta sjĂ€lva.

* Det gick inte att köra Swoole-koroutiner med Parallel, det verkar som om dessa tillÀgg Àr inkompatibla.

SĂ„, de slutgiltiga resultaten:

Accelerera PHP-kopplingen för Tarantool med Async, Swoole och Parallel

Avslutande

Jag tycker resultaten Ă€r ganska lovande, och jag Ă€r övertygad om att detta inte Ă€r slutet! Huruvida detta Ă€r nĂ„got ni behöver i ert verkliga projekt, det avgör ni helt sjĂ€lva. Jag vill bara sĂ€ga att detta var ett intressant experiment som ger en uppfattning om hur mycket man kan "pressa" ur en synkron TCP-anslutning med minsta möjliga anstrĂ€ngning. Om ni har idĂ©er för att förbĂ€ttra benchmarkningarna – jag ser gĂ€rna över er pull request. All kod med instruktioner för körning och resultat har publicerats i ett separat förrĂ„det.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster