ProHoster > Blogi > antaminen > 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".
* 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:
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:
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):
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:
"Levitä" 10,000 25 operaatiota XNUMX korutiiniin ja katso mitä tapahtuu:
Valitettavasti PECL-liitin ei alkanut ext-asyncillä.
Entä SQL?
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:
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:
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:
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ä:
Se on sama kuin 16 koneellani. Suoritetaan liittimen vertailuarvot 16 rinnakkaisella kierteellä:
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.
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:
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.