Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel

PHP ekosistemoje šiuo metu yra dvi jungtys darbui su Tarantool serveriu – tai oficialus PECL plėtinys tarantool/tarantool-php, parašyta C ir tarantool-php/klientas, parašyta PHP. Aš esu pastarojo autorius.

Šiame straipsnyje norėčiau pasidalinti abiejų bibliotekų našumo testavimo rezultatais ir parodyti, kaip su minimaliais kodo pakeitimais galite pasiekti 3–5 našumo padidėjimą (apie sintetinius testus!).

Ką mes išbandysime?

Išbandysime aukščiau paminėtus sinchroninis jungtys, veikiančios asinchroniškai, lygiagrečiai ir asinchroniškai lygiagrečiai. 🙂 Taip pat nenorime liesti pačių jungčių kodo. Šiuo metu yra keletas plėtinių, kad pasiektumėte tai, ko norite:

  • Swoole ― didelio našumo asinchroninė PHP sistema. Naudoja tokie interneto gigantai kaip Alibaba ir Baidu. Nuo 4.1.0 versijos atsirado magiškas metodas SwooleRuntime::enableCoroutine(), kuri leidžia „konvertuoti sinchronines PHP tinklo bibliotekas į asinchronines su viena kodo eilute“.
  • Async dar visai neseniai buvo labai perspektyvus asinchroninio darbo PHP plėtinys. Kodėl dar visai neseniai? Deja, dėl man nežinomos priežasties autorius ištrynė saugyklą ir tolimesnis projekto likimas neaiškus. Aš turėsiu juo pasinaudoti одним iš šakių. Kaip ir „Swoole“, šis plėtinys leidžia lengvai įjungti kelnes riešo brūkštelėjimu, kad įgalintumėte asinchroniją, pakeičiant standartinį TCP ir TLS srautų diegimą jų asinchroninėmis versijomis. Tai atliekama naudojant parinktį "async.tcp = 1"
  • Parallel ― gana naujas plėtinys iš gerai žinomo Joe Watkins, tokių bibliotekų kaip phpdbg, apcu, pthreads, pcov, uopz autoriaus. Plėtinys suteikia API, skirtą kelių gijų kūrimui PHP, ir yra sukurtas kaip pthreadų pakaitalas. Reikšmingas bibliotekos apribojimas yra tas, kad ji veikia tik su ZTS (Zend Thread Safe) PHP versija.

Kaip mes išbandysime?

Paleiskite Tarantool egzempliorių su išjungtu įrašymo į priekį registravimu (wal_mode = nėra) ir padidintas tinklo buferis (skaitymas į priekį = 1 * 1024 * 1024). Pirmoji parinktis pašalins darbą su disku, antroji leis perskaityti daugiau užklausų iš operacinės sistemos buferio ir taip sumažinti sistemos skambučių skaičių.

Etalonams, kurie veikia su duomenimis (įterpimas, ištrynimas, skaitymas ir kt.), prieš pradedant etaloną bus (iš naujo) sukurta memtx erdvė, kurioje pirminės indekso reikšmės sukuriamos tvarkingų sveikųjų skaičių reikšmių generatoriaus. (seka).
Erdvė DDL atrodo taip:

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

Jei reikia, prieš paleidžiant etaloną, vieta užpildoma 10,000 XNUMX formos kortelių

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

Kortelės pasiekiamos naudojant atsitiktinę rakto reikšmę.

Pats etalonas yra viena užklausa serveriui, kuri vykdoma 10,000 5 kartų (apsukimų), kurie, savo ruožtu, vykdomi iteracijomis. Iteracijos kartojamos tol, kol visi laiko nuokrypiai tarp 3 iteracijų neviršija priimtinos 1% paklaidos*. Po to imamas vidutinis rezultatas. Tarp pakartojimų yra XNUMX sekundės pauzė, kad procesorius nesumažėtų. Lua šiukšlių rinktuvas išjungiamas prieš kiekvieną iteraciją ir yra priverstas paleisti jam pasibaigus. PHP procesas paleidžiamas tik naudojant etalonui būtinus plėtinius, įjungus išvesties buferį ir išjungus šiukšlių rinktuvą.

* Apsisukimų skaičius, iteracijos ir klaidų slenkstis gali būti keičiami etalono nustatymuose.

Bandymo aplinka

Žemiau paskelbti rezultatai buvo gauti naudojant MacBookPro (2015), operacinė sistema – Fedora 30 (branduolio versija 5.3.8-200.fc30.x86_64). „Tarantool“ buvo paleistas „Docker“ su parametru „--network host".

Paketo versijos:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, build a872fc2f86
PHP: 7.3.11 (cli) (pastatyta: 22 m. spalio 2019 d., 08:11:04)
tarantool/klientas: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ pleistras 7.3)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ex-swoole: 4.4.12
išorinis lygiagretus: 1.1.3

* Deja, oficiali jungtis neveikia su PHP versija > 7.2. Norėdami kompiliuoti ir paleisti plėtinį PHP 7.3 versijoje, turėjau naudoti pleistras.

rezultatai

Sinchroninis režimas

Tarantool protokolas naudoja dvejetainį formatą MessagePack serializuoti pranešimus. PECL jungtyje serializavimas yra paslėptas giliai bibliotekos gelmėse ir turi įtakos kodavimo procesui iš vartotojo krašto kodo neatrodo įmanoma. Gryna PHP jungtis, priešingai, suteikia galimybę tinkinti kodavimo procesą išplečiant standartinį kodavimo įrenginį arba naudojant savo diegimą. Yra du kodavimo įrenginiai, kurių vienas yra pagrįstas msgpack/msgpack-php (oficialus „MessagePack PECL“ plėtinys), kitas įjungtas rybakit/msgpack (grynu PHP).

Prieš lygindami jungtis, išmatuosime PHP jungties MessagePack kodavimo įrenginių našumą ir tolesniuose bandymuose naudosime tą, kuris parodys geriausią rezultatą:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Nors PHP versija (Pure) savo greičiu prastesnė už PECL plėtinį, realiuose projektuose vis tiek rekomenduočiau ją naudoti rybakit/msgpack, nes oficialiame „MessagePack“ plėtinyje formato specifikacija įdiegta tik iš dalies (pavyzdžiui, nepalaikomi pasirinktiniai duomenų tipai, be kurių negalėsite naudoti „Decimal“ – naujo duomenų tipo, pristatyto Tarantool 2.3 versijoje) ir turi kitų skaičius problemų (įskaitant suderinamumo su PHP 7.4 problemas). Na, apskritai projektas atrodo apleistas.

Taigi, išmatuokime jungčių našumą sinchroniniu režimu:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Kaip matyti iš grafiko, PECL jungtis (Tarantool) rodo geresnį našumą, palyginti su PHP jungtimi (klientu). Tačiau tai nenuostabu, nes pastaroji, be to, kad yra įdiegta lėtesne kalba, iš tikrųjų atlieka daugiau darbo: su kiekvienu skambučiu sukuriamas naujas objektas Prašymas и atsakymas (Pasirinkus - taip pat Kriterijai, o atnaujinimo / atnaujinimo atveju ― operacijos), atskiri subjektai Ryšys, Pakuotojas и Valdytojas jie taip pat prideda pridėtines išlaidas. Akivaizdu, kad lankstumas turi savo kainą. Tačiau apskritai PHP interpretatorius rodo gerą našumą, nors skirtumas yra, jis yra nereikšmingas ir, galbūt, bus dar mažesnis naudojant išankstinį įkėlimą PHP 7.4, jau nekalbant apie JIT PHP 8.

Eikime toliau. Tarantool 2.0 pridėjo SQL palaikymą. Pabandykime atlikti Select, Insert, Update ir Delete operacijas naudodami SQL protokolą ir palyginkime rezultatus su noSQL (dvejetainiais) ekvivalentais:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
SQL rezultatai nėra labai įspūdingi (priminsiu, kad vis dar testuojame sinchroninį režimą). Tačiau aš nenusiminčiau dėl to anksčiau laiko, SQL palaikymas vis dar aktyviai vystomas (palyginti neseniai, pavyzdžiui, buvo pridėtas palaikymas parengtus pareiškimus) ir, sprendžiant iš sąrašo klausimai, ateityje SQL variklis bus optimizuotas.

Asinchronizacija

Na, o dabar pažiūrėkime, kaip Async plėtinys gali padėti mums pagerinti aukščiau pateiktus rezultatus. Norėdami rašyti asinchronines programas, plėtinys suteikia API, pagrįstą korutinėmis, kurias naudosime. Empiriškai išsiaiškiname, kad optimalus korotinų skaičius mūsų aplinkai yra 25:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
„Išskleiskite“ 10,000 25 operacijų XNUMX programose ir pažiūrėkite, kas atsitiks:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Operacijų skaičius per sekundę padidėjo daugiau nei 3 kartus tarantool-php/klientas!

Deja, PECL jungtis neprasidėjo su ext-async.

O kaip su SQL?

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Kaip matote, asinchroniniu režimu skirtumas tarp dvejetainio protokolo ir SQL buvo paklaidos ribose.

Swoole

Vėlgi, mes sužinome optimalų korutinų skaičių, šį kartą Swoole:
Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Sustokime ties 25. Pakartokime tą patį triuką kaip ir su Async plėtiniu – paskirstykite 10,000 25 operacijų tarp 2 korutinų. Be to, pridėsime dar vieną testą, kuriame visą darbą suskirstysime į 5,000 du procesus (tai yra, kiekvienas procesas atliks 25 operacijų XNUMX-iose korutinose). Procesai bus sukurti naudojant SwooleProcess.

Rezultatai:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Swole rodo kiek mažesnį rezultatą lyginant su Async paleidus viename procese, bet su 2 procesais vaizdas kardinaliai pasikeičia (skaičius 2 pasirinktas neatsitiktinai, mano mašinoje geriausią rezultatą rodė 2 procesai).

Beje, Async plėtinys taip pat turi API darbui su procesais, bet ten nepastebėjau jokio skirtumo nuo benchmarkų vykdymo viename ar keliuose procesuose (gali būti, kad kur nors susipainiojau).

SQL prieš dvejetainį protokolą:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Kaip ir Async atveju, skirtumas tarp dvejetainių ir SQL operacijų pašalinamas asinchroniniu režimu.

Parallel

Kadangi lygiagretus plėtinys yra susijęs ne su korutomis, o su gijomis, išmatuokime optimalų lygiagrečių gijų skaičių:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Mano mašinoje jis lygus 16. Atlikime jungties etalonus 16 lygiagrečių gijų:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Kaip matote, rezultatas yra net geresnis nei naudojant asinchroninius plėtinius (neskaičiuojant Swoole, veikiančio 2 procesuose). Atminkite, kad PECL jungties atnaujinimo ir atnaujinimo operacijos yra tuščios. Taip yra dėl to, kad šios operacijos nepavyko dėl klaidos – nežinau, ar tai buvo ext-parallel, ext-tarantool, ar abiejų kaltė.

Dabar palyginkime SQL našumą:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel
Pastebite panašumą su sinchroniškai veikiančių jungčių diagrama?

Kartu

Ir galiausiai apibendrinkime visus rezultatus vienoje diagramoje, kad pamatytume bendrą patikrintų plėtinių vaizdą. Prie diagramos pridėkime tik vieną naują testą, kurio dar nepadarėme – lygiagrečiai paleisime Async korutinas naudodami Parallel*. Idėja integruoti minėtus plėtinius jau yra buvo aptarta autorių, tačiau bendro sutarimo nepasiekta, teks tai padaryti patiems.

* Nebuvo įmanoma paleisti Swoole korutinos su Parallel; atrodo, kad šie plėtiniai yra nesuderinami.

Taigi, galutiniai rezultatai:

Tarantool skirtų PHP jungčių spartinimas naudojant Async, Swoole ir Parallel

Vietoj išvados

Mano nuomone, rezultatai pasirodė gana verti, ir dėl tam tikrų priežasčių esu tikras, kad tai nėra riba! Ar realiame projekte tai reikia spręsti tik pačiam, pasakysiu tik tiek, kad man tai buvo įdomus eksperimentas, leidžiantis įvertinti, kiek galima minimaliomis pastangomis „išspausti“ iš sinchroninės TCP jungties. Jei turite idėjų, kaip pagerinti etalonus, mielai apsvarstysiu jūsų prašymą. Visas kodas su paleidimo instrukcijomis ir rezultatais skelbiamas atskirame leidinyje saugyklos.

Šaltinis: www.habr.com

Добавить комментарий