Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja

PHP-ekosysteemissä on tällä hetkellä kaksi liitintä työskennellä Tarantool-palvelimen kanssa - tämä on virallinen PECL-laajennus tarantool/tarantool-php, kirjoitettu C-kielellä ja tarantool-php/client, kirjoitettu PHP:llä. Olen jälkimmäisen kirjoittaja.

Tässä artikkelissa haluan jakaa molempien kirjastojen suorituskykytestauksen tulokset ja näyttää, kuinka voit saavuttaa 3–5 suorituskyvyn lisäyksen pienillä koodin muutoksilla (synteettisissä testeissä!).

Mitä testaamme?

Testaamme yllämainittuja synkroninen liittimet, jotka toimivat asynkronisesti, rinnakkain ja asynkronisesti rinnakkain. 🙂 Emme myöskään halua koskea itse liittimien koodiin. Tällä hetkellä saatavilla on useita laajennuksia, joiden avulla voit saavuttaa haluamasi:

  • Swoole ― korkean suorituskyvyn asynkroninen kehys PHP:lle. Sitä käyttävät sellaiset Internet-jättiläiset kuin Alibaba ja Baidu. Versiosta 4.1.0 lähtien on ilmestynyt taikamenetelmä SwooleRuntime::enableCoroutine(), jonka avulla voit "muuntaa synkroniset PHP-verkkokirjastot asynkronisiksi yhdellä koodirivillä".
  • Async oli viime aikoihin asti erittäin lupaava laajennus asynkroniseen työhön PHP:ssa. Miksi viime aikoihin asti? Valitettavasti kirjoittaja poisti minulle tuntemattomasta syystä arkiston ja projektin tuleva kohtalo on epäselvä. Minun täytyy käyttää sitä одним haarukoista. Kuten Swoolen, tämän laajennuksen avulla voit helposti kytkeä housut päälle yhdellä ranteen pyyhkäisyllä ja mahdollistaa asynkronisuuden korvaamalla TCP- ja TLS-virtojen vakiototeutuksen niiden asynkronisilla versioilla. Tämä tehdään vaihtoehdolla "async.tcp = 1".
  • Parallel ― melko uusi laajennus tunnetulta Joe Watkinsilta, joka on sellaisten kirjastojen kirjoittaja kuin phpdbg, apcu, pthreads, pcov, uopz. Laajennus tarjoaa API:n monisäikeistykseen PHP:ssä, ja se on sijoitettu pthread-säikeiden korvaajaksi. Kirjaston merkittävä rajoitus on, että se toimii vain PHP:n ZTS (Zend Thread Safe) -version kanssa.

Miten testaamme?

Käynnistetään Tarantool-esiintymä, jossa eteenpäinkirjoitus on poistettu käytöstä (wal_mode = ei mitään) ja lisääntynyt verkkopuskuri (luku eteenpäin = 1 * 1024 * 1024). Ensimmäinen vaihtoehto poistaa työskentelyn levyn kanssa, toinen mahdollistaa enemmän pyyntöjen lukemisen käyttöjärjestelmän puskurista ja siten minimoi järjestelmäkutsujen määrän.

Vertailuarvoille, jotka toimivat datan kanssa (lisäys, poistaminen, lukeminen jne.), ennen vertailuarvon aloittamista luodaan (uudelleen) memtx-avaruus, jossa ensisijaiset indeksiarvot luodaan järjestetyn kokonaislukuarvon generaattorilla. (sekvenssi).
DDL-avaruus näyttää tältä:

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

Tarvittaessa tila täytetään ennen benchmarkin suorittamista 10,000 XNUMX lomakkeella

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

Tupleihin päästään käyttämällä satunnaisavaimen arvoa.

Vertailuarvo itsessään on yksittäinen pyyntö palvelimelle, joka suoritetaan 10,000 5 kertaa (kierrosta), jotka puolestaan ​​suoritetaan iteraatioina. Iteraatioita toistetaan, kunnes kaikki aikapoikkeamat 3 iteraation välillä ovat hyväksyttävän 1 %:n* virheen sisällä. Tämän jälkeen otetaan keskimääräinen tulos. Toistojen välillä on XNUMX sekunnin tauko, jotta prosessori ei häiritse. Luan roskankeräys poistetaan käytöstä ennen jokaista iteraatiota, ja sen on käynnistettävä sen valmistumisen jälkeen. PHP-prosessi käynnistetään vain vertailuarvoon tarvittavilla laajennuksilla, lähtöpuskurointi on käytössä ja roskakeräin pois käytöstä.

* Kierrosten lukumäärää, iteraatioita ja virhekynnystä voidaan muuttaa vertailuarvojen asetuksissa.

Testiympäristössä

Alla julkaistut tulokset on tehty MacBookProlla (2015), käyttöjärjestelmä - Fedora 30 (ytimen versio 5.3.8-200.fc30.x86_64). Tarantool käynnistettiin Dockerissa parametrilla "--network host".

Paketin versiot:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, build a872fc2f86
PHP: 7.3.11 (cli) (rakennettu: 22. lokakuuta 2019 08:11:04)
tarantool/asiakas: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ korjaustiedosto 7.3:lle)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12
ulkopuolinen: 1.1.3

* Valitettavasti virallinen liitin ei toimi PHP-versiolla > 7.2. Laajennuksen kääntämiseksi ja suorittamiseksi PHP 7.3:ssa minun piti käyttää laastari.

Tulokset

Synkroninen tila

Tarantool-protokolla käyttää binaarimuotoa MessagePack viestien sarjoittamiseksi. PECL-liittimessä serialisointi on piilotettu syvälle kirjaston syvyyksiin ja vaikuttaa käyttäjämaakoodin koodausprosessiin ei näytä mahdolliselta. Puhdas PHP-liitin päinvastoin tarjoaa mahdollisuuden mukauttaa koodausprosessia laajentamalla vakiokooderia tai käyttämällä omaa toteutustasi. Saatavilla on kaksi enkooderia, joista toinen perustuu msgpack/msgpack-php (virallinen MessagePack PECL-laajennus), toinen on päällä rybakit/msgpack (puhdas PHP).

Ennen liittimien vertailua mittaamme PHP-liittimen MessagePack-enkooderien suorituskyvyn ja jatkotesteissä käytämme sitä, joka näyttää parhaan tuloksen:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Vaikka PHP-versio (Pure) on nopeudeltaan huonompi kuin PECL-laajennus, suosittelen silti oikeissa projekteissa sen käyttöä rybakit/msgpack, koska virallisessa MessagePack-laajennuksessa muotomäärittely on toteutettu vain osittain (esimerkiksi mukautetuille tietotyypeille ei ole tukea, jota ilman et voi käyttää Decimaalia - uutta tietotyyppiä, joka on otettu käyttöön Tarantool 2.3:ssa) ja siinä on muiden määrä ongelmia (mukaan lukien yhteensopivuusongelmat PHP 7.4:n kanssa). No, yleisesti ottaen projekti näyttää hylätyltä.

Joten, mitataan liittimien suorituskykyä synkronisessa tilassa:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Kuten kaaviosta näkyy, PECL-liitin (Tarantool) näyttää paremman suorituskyvyn verrattuna PHP-liittimeen (Client). Mutta tämä ei ole yllättävää, kun otetaan huomioon, että jälkimmäinen sen lisäksi, että se toteutetaan hitaammalla kielellä, tekee itse asiassa enemmän työtä: uusi objekti luodaan jokaisella kutsulla Pyydä и Vastaus (Valinnan tapauksessa - myös Kriteeri, ja Update/Upsert tapauksessa ― Operations), erilliset kokonaisuudet Yhteys, Pakkaaja и Käsittelijä ne lisäävät myös yleiskustannuksia. On selvää, että joustavuudella on hintansa. Yleisesti ottaen PHP-tulkki näyttää kuitenkin hyvää suorituskykyä, vaikka eroa onkin, se on merkityksetön ja ehkä vielä vähemmän, kun käytetään esilatausta PHP 7.4:ssä, puhumattakaan JIT:stä PHP 8:ssa.

Siirrytään eteenpäin. Tarantool 2.0 esitteli SQL-tuen. Yritetään suorittaa Select-, Insert-, Update- ja Delete-operaatiot SQL-protokollan avulla ja verrataan tuloksia noSQL-vastaaviin (binäärimuotoihin):

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
SQL-tulokset eivät ole kovin vaikuttavia (muistutan, että testaamme edelleen synkronista tilaa). Tästä en kuitenkaan suuttuisi etukäteen, SQL-tuki on vielä aktiivisesti kehitteillä (suhteellisen äskettäin mm. valmistetut lausunnot) ja luettelosta päätellen kysymykset, SQL-moottorille tehdään useita optimointeja tulevaisuudessa.

async

Katsotaanpa nyt, kuinka Async-laajennus voi auttaa meitä parantamaan yllä olevia tuloksia. Asynkronisten ohjelmien kirjoittamiseen laajennus tarjoaa korutiineihin perustuvan API:n, jota käytämme. Havaitsemme empiirisesti, että optimaalinen korutiinimäärä ympäristöllemme on 25:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
"Levitä" 10,000 25 operaatiota XNUMX korutiiniin ja katso mitä tapahtuu:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Toimintojen määrä sekunnissa kasvoi yli 3 kertaa tarantool-php/client!

Valitettavasti PECL-liitin ei alkanut ext-asyncillä.

Entä SQL?

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Kuten näet, asynkronisessa tilassa binaariprotokollan ja SQL:n välinen ero tuli virhemarginaalin sisällä.

Swoole

Selvitämme jälleen optimaalisen korutiinien määrän, tällä kertaa Swoolelle:
Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Pysähdytään 25:een. Toistetaan sama temppu kuin Async-laajennuksen kanssa - jaa 10,000 25 operaatiota 2 korutiinin kesken. Lisäksi lisäämme toisen testin, jossa jaamme kaiken työn kahteen kahteen prosessiin (eli jokainen prosessi suorittaa 5,000 25 toimintoa XNUMX korutiinissa). Prosessit luodaan käyttämällä SwooleProcess.

tulokset:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Swole näyttää hieman heikompaa tulosta verrattuna Asynciin yhdellä prosessilla ajettaessa, mutta kahdella prosessilla kuva muuttuu dramaattisesti (numero 2 ei valittu sattumalta, omalla koneellani 2 prosessia näytti parhaan tuloksen).

Muuten, Async-laajennuksessa on myös API prosessien kanssa työskentelyä varten, mutta siellä en huomannut mitään eroa vertailuarvojen suorittamiseen yhdessä tai useammassa prosessissa (on mahdollista, että olen sotkenut jossain).

SQL vs binääriprotokolla:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Kuten Asyncissä, ero binääri- ja SQL-toimintojen välillä poistetaan asynkronisessa tilassa.

Parallel

Koska Rinnakkaislaajennus ei koske korutiineja, vaan säikeitä, mitataan optimaalinen rinnakkaisten säikeiden lukumäärä:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Se on sama kuin 16 koneellani. Suoritetaan liittimen vertailuarvot 16 rinnakkaisella kierteellä:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Kuten näet, tulos on jopa parempi kuin asynkronisilla laajennuksilla (lukuun ottamatta Swoolea, joka toimii kahdessa prosessissa). Huomaa, että PECL-liittimen Update- ja Upsert-toiminnot ovat tyhjiä. Tämä johtuu siitä, että nämä toiminnot epäonnistuivat virheellä - en tiedä, oliko se ext-parallel-, ext-tarantool- tai molempien vika.

Verrataan nyt SQL:n suorituskykyä:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja
Huomaatko samankaltaisuuden synkronisesti toimivien liittimien kaavion kanssa?

Yhdessä

Ja lopuksi yhteenveto kaikista tuloksista yhteen kaavioon nähdäksesi kokonaiskuvan testatuista laajennuksista. Lisätään kaavioon vain yksi uusi testi, jota emme ole vielä tehneet - ajetaan Async-korutiinit rinnakkain Parallel* -toiminnolla. Ajatus yllä olevien laajennusten integroimisesta on jo olemassa keskusteltu kirjoittajat, mutta yhteisymmärrykseen ei päästy, sinun on tehtävä se itse.

* Swoole-korutiineja ei voitu käynnistää Parallelin kanssa; näyttää siltä, ​​​​että nämä laajennukset eivät ole yhteensopivia.

Eli lopputulokset:

Kiihdyttävät PHP-liittimet Tarantoolille käyttämällä Async-, Swoole- ja Parallel-toimintoja

Sen sijaan johtopäätös

Mielestäni tulokset osoittautuivat varsin arvokkaiksi, ja jostain syystä olen varma, että tämä ei ole raja! Riippumatta siitä, tarvitseeko sinun päättää tämä todellisessa projektissa vain itsellesi, sanon vain, että minulle se oli mielenkiintoinen kokeilu, jonka avulla voit arvioida, kuinka paljon voit "puristaa" synkronisesta TCP-liittimestä vähällä vaivalla. Jos sinulla on ideoita vertailuarvojen parantamiseksi, otan mielelläni vetopyyntösi huomioon. Kaikki koodi käynnistysohjeineen ja tuloksineen julkaistaan ​​erillisenä arkistot.

Lähde: will.com

Lisää kommentti