Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна

PHP экосистемд одоогоор Tarantool сервертэй ажиллах хоёр холбогч байгаа бөгөөд энэ нь албан ёсны PECL өргөтгөл юм. tarantool/tarantool-php, C хэлээр бичигдсэн, мөн tarantool-php/client, PHP дээр бичигдсэн. Би сүүлчийнх нь зохиогч юм.

Энэ нийтлэлд би хоёр номын сангийн гүйцэтгэлийн туршилтын үр дүнг хуваалцаж, кодын хамгийн бага өөрчлөлтөөр та гүйцэтгэлийг 3-5 дахин нэмэгдүүлэх боломжтой болохыг харуулахыг хүсч байна (синтетик туршилтууд дээр!).

Бид юу шалгах вэ?

Бид дээр дурдсан зүйлсийг туршиж үзэх болно синхрон асинхрон, зэрэгцээ, асинхрон-параллель ажиллаж байгаа холбогч. 🙂 Бид мөн холбогчдын кодыг өөрөө хөндөхийг хүсэхгүй байна. Одоогоор таны хүссэн зүйлд хүрэх хэд хэдэн өргөтгөлүүд байна:

  • Swoole ― PHP-д зориулсан өндөр гүйцэтгэлтэй асинхрон хүрээ. Алибаба, Байду зэрэг интернетийн аварга компаниуд ашигладаг. 4.1.0 хувилбараас хойш ид шидийн арга бий болсон SwooleRuntime::enableCoroutine(), энэ нь танд "синхрон PHP сүлжээний сангуудыг нэг мөр кодын тусламжтайгаар асинхрон болгон хөрвүүлэх" боломжийг олгодог.
  • Async нь саяхныг хүртэл PHP дахь асинхрон ажилд маш ирээдүйтэй өргөтгөл байсан. Яагаад саяхныг хүртэл? Харамсалтай нь, надад үл мэдэгдэх шалтгаанаар зохиогч уг санг устгасан бөгөөд төслийн цаашдын хувь заяа тодорхойгүй байна. Би үүнийг ашиглах хэрэгтэй болно нэг нь сэрээнээс. Swoole-ийн нэгэн адил энэхүү өргөтгөл нь TCP болон TLS урсгалуудын стандарт хэрэгжилтийг асинхрон хувилбараар сольж асинхроныг идэвхжүүлэхийн тулд бугуйгаа гүйлгэх замаар өмдөө хялбархан эргүүлэх боломжийг олгоно. Үүнийг " сонголтоор хийдэг.async.tcp = 1".
  • Зэрэгцээ ― phpdbg, apcu, pthreads, pcov, uopz зэрэг номын сангийн зохиогч Жо Уоткинсийн нэлээд шинэ өргөтгөл. Өргөтгөл нь PHP хэл дээр олон урсгалтай ажиллах API-г өгдөг бөгөөд pthreads-ийг орлуулах байдлаар байрладаг. Номын сангийн томоохон хязгаарлалт нь зөвхөн PHP-ийн ZTS (Zend Thread Safe) хувилбартай ажилладагт оршино.

Бид яаж тест хийх вэ?

Урьдчилан бичих бүртгэлийг идэвхгүй болгосон Tarantool жишээг ажиллуулцгаая (wal_mode = байхгүй) болон нэмэгдсэн сүлжээний буфер (өмнө нь унших = 1 * 1024 * 1024). Эхний сонголт нь дисктэй ажиллахгүй байх болно, хоёр дахь нь үйлдлийн системийн буферээс илүү олон хүсэлтийг унших боломжтой болгож, улмаар системийн дуудлагын тоог багасгах болно.

Өгөгдөлтэй ажилладаг жишиг үзүүлэлтүүдийн хувьд (оруулах, устгах, унших гэх мэт) жишиг шалгуурыг эхлүүлэхийн өмнө үндсэн индексийн утгуудыг эрэмбэлэгдсэн бүхэл тоонуудын үүсгэгчээр үүсгэсэн memtx зай (дахин) үүсгэнэ. (дараалал).
DDL зай дараах байдалтай байна.

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

Шаардлагатай бол жишиг тестийг ажиллуулахын өмнө орон зайг маягтын 10,000 tuple дүүргэнэ.

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

Tuple-д санамсаргүй түлхүүрийн утгыг ашиглан ханддаг.

Жишиг нь өөрөө серверт нэг хүсэлт бөгөөд үүнийг 10,000 удаа (хувьсгал) гүйцэтгэдэг бөгөөд энэ нь эргээд давталтаар хийгддэг. 5 давталтын хоорондох бүх цаг хугацааны хазайлт нь 3%*-ийн хүлээн зөвшөөрөгдөх алдаатай байх хүртэл давталтуудыг давтана. Үүний дараа дундаж үр дүнг авна. Процессорыг багасгахаас сэргийлэхийн тулд давталтуудын хооронд 1 секундын завсарлага байдаг. Луагийн хог цуглуулагчийг давталт бүрийн өмнө идэвхгүй болгосон бөгөөд дууссаны дараа эхлүүлэхээс өөр аргагүй болдог. PHP процесс нь зөвхөн жишиг үзүүлэлтэд шаардлагатай өргөтгөлүүдийг суулгаж, гаралтын буферийг идэвхжүүлж, хог цуглуулагчийг идэвхгүй болгож ажиллуулдаг.

* Эргэлтийн тоо, давталт, алдааны босго зэргийг жишиг тохиргоонд өөрчилж болно.

Туршилтын орчин

Доор нийтлэгдсэн үр дүнг MacBookPro (2015), үйлдлийн систем - Fedora 30 (цөмийн хувилбар 5.3.8-200.fc30.x86_64) дээр хийсэн. Tarantool-ийг докер дээр "параметрээр эхлүүлсэн.--network host".

Багцын хувилбарууд:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, a872fc2f86 бүтээх
PHP: 7.3.11 (cli) (суулгасан: 22 оны 2019-р сарын 08 11:04:XNUMX)
tarantool/үйлчлүүлэгч: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ 7.3-ийн засвар)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12
гаднах зэрэгцээ: 1.1.3

* Харамсалтай нь албан ёсны холбогч нь PHP > 7.2 хувилбартай ажиллахгүй байна. Өргөтгөлийг PHP 7.3 дээр хөрвүүлж ажиллуулахын тулд би ашиглах хэрэгтэй болсон нөхөөс.

Результаты

Синхрон горим

Tarantool протокол нь хоёртын форматыг ашигладаг MessagePack зурвасуудыг цуваа болгох. PECL холбогч дээр цувралжуулалт нь номын сангийн гүнд нуугдаж, хэрэглэгчийн кодоос кодлох үйл явцад нөлөөлдөг. боломжгүй юм шиг байна. Цэвэр PHP холбогч нь эсрэгээрээ стандарт кодлогчийг өргөтгөх эсвэл өөрийн хэрэгжүүлэлтийг ашиглан кодчилолын процессыг өөрчлөх боломжийг олгодог. Хайрцагнаас гарах боломжтой хоёр кодлогч байдаг бөгөөд нэг нь дээр суурилсан msgpack/msgpack-php (албан ёсны MessagePack PECL өргөтгөл), нөгөө нь асаалттай байна rybakit/msgpack (цэвэр PHP дээр).

Холбогчдыг харьцуулахын өмнө бид PHP холбогчдод зориулсан MessagePack кодлогчийн гүйцэтгэлийг хэмжиж, цаашдын туршилтуудад хамгийн сайн үр дүнг харуулсаныг ашиглана.

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
Хэдийгээр PHP хувилбар (Цэвэр) нь хурдны хувьд PECL өргөтгөлөөс доогуур боловч бодит төслүүдэд үүнийг ашиглахыг зөвлөж байна. rybakit/msgpack, учир нь албан ёсны MessagePack өргөтгөл дээр форматын тодорхойлолт нь зөвхөн хэсэгчлэн хэрэгждэг (жишээ нь, захиалгат өгөгдлийн төрлийг дэмждэггүй, үүнгүйгээр та Decimal ашиглах боломжгүй - Tarantool 2.3-д нэвтрүүлсэн шинэ өгөгдлийн төрөл) ба бусдын тоо асуудлууд (PHP 7.4-тэй нийцтэй байдлын асуудлууд орно). За, ерөнхийдөө төсөл нь орхигдсон юм шиг байна.

Тиймээс синхрон горимд холбогчдын гүйцэтгэлийг хэмжье.

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
Графикаас харахад PECL холбогч (Tarantool) нь PHP холбогч (Клиент) -тэй харьцуулахад илүү сайн гүйцэтгэлтэй байгааг харуулж байна. Гэхдээ энэ нь удаан хэлээр хэрэгжихээс гадна илүү их ажил хийдэг тул энэ нь гайхмаар зүйл биш юм: дуудлага болгонд шинэ объект үүсдэг. авагч и хариу арга хэмжээ (сонгосон тохиолдолд - мөн Шалгуур, мөн Шинэчлэх/Дээш оруулах тохиолдолд ― үйл ажиллагаа), тусдаа аж ахуйн нэгжүүд Холболтын, Пакер и Зохицуулагч Тэд мөн нэмэлт зардлыг нэмдэг. Мэдээжийн хэрэг, уян хатан байдал нь үнэтэй байдаг. Гэсэн хэдий ч ерөнхийдөө PHP орчуулагч нь сайн гүйцэтгэлийг харуулдаг, гэхдээ ялгаа байгаа ч энэ нь ач холбогдолгүй бөгөөд PHP 7.4 дээр урьдчилан ачаалах үед PHP 8 дээр JIT-ийг дурдахгүй байх нь бүр ч бага байх болно.

Үргэлжлүүлье. Tarantool 2.0 нь SQL-ийн дэмжлэгийг нэмсэн. Сонгох, оруулах, шинэчлэх, устгах үйлдлүүдийг SQL протокол ашиглан хийж, үр дүнг noSQL (хоёртын) эквиваленттай харьцуулж үзье.

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
SQL-ийн үр дүн тийм ч гайхалтай биш байна (бид синхрон горимыг туршиж байгаа гэдгийг танд сануулъя). Гэсэн хэдий ч би үүнд урьдчилж бухимдахгүй байх байсан; SQL дэмжлэг идэвхтэй хөгжиж байгаа хэвээр байна (харьцангуй саяхан, жишээ нь дэмжлэг нэмэгдсэн байна. мэдэгдэл бэлтгэсэн) болон жагсаалтаас харахад асуудлууд, SQL хөдөлгүүр нь ирээдүйд хэд хэдэн оновчлолд орох болно.

Асинк

За, одоо Async өргөтгөл нь дээрх үр дүнг сайжруулахад хэрхэн тусалж болохыг харцгаая. Асинхрон программ бичихийн тулд өргөтгөл нь coroutines дээр суурилсан API-г өгдөг бөгөөд үүнийг бидний ашиглах болно. Бидний хүрээлэн буй орчны хамгийн оновчтой тоо нь 25 гэдгийг бид эмпирик байдлаар олж мэдсэн.

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
10,000 корутинд 25 үйлдлийг "тархаж", юу болохыг хараарай:

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
секундэд хийх үйлдлийн тоо 3 дахин нэмэгджээ tarantool-php/client!

Харамсалтай нь PECL холбогч нь ext-async-ээр эхлээгүй байна.

SQL-ийн талаар юу хэлэх вэ?

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
Таны харж байгаагаар асинхрон горимд хоёртын протокол ба SQL-ийн ялгаа нь алдааны хязгаарт хүрсэн байна.

Swoole

Энэ удаад Свулийн хувьд бид корутинуудын оновчтой тоог дахин олж мэдэв.
Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
25 дээр зогсооцгооё. Async өргөтгөлтэй адил трик давтъя - 10,000 корутин хооронд 25 үйлдлийг хуваарил. Нэмж дурдахад бид бүх ажлыг 2 хоёр процесст хуваах өөр нэг тестийг нэмж оруулах болно (өөрөөр хэлбэл процесс бүр 5,000 корутинд 25 үйлдлийг гүйцэтгэх болно). Процессуудыг ашиглан үүсгэнэ SwooleProcess.

Үр дүн:

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
Swole нь нэг процесс дээр ажиллахад Async-тэй харьцуулахад арай бага үр дүнг харуулдаг боловч 2 процесст зураг эрс өөрчлөгддөг (2-ын тоог санамсаргүй байдлаар сонгоогүй; миний машин дээр 2 процесс хамгийн сайн үр дүнг харуулсан).

Дашрамд хэлэхэд, Async өргөтгөл нь процессуудтай ажиллах API-тай боловч тэнд би нэг буюу хэд хэдэн процесст жишиг тогтоохоос ямар ч ялгааг анзаараагүй (би хаа нэгтээ будлиулсан байж магадгүй).

SQL болон хоёртын протокол:

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
Async-ийн нэгэн адил хоёртын болон SQL үйлдлийн хоорондын ялгаа асинхрон горимд арилдаг.

Зэрэгцээ

Зэрэгцээ өргөтгөл нь корутинуудын тухай биш, харин утаснуудын тухай тул зэрэгцээ утаснуудын оновчтой тоог хэмжье.

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
Энэ нь миний машин дээр 16-тай тэнцүү байна. 16 зэрэгцээ утаснуудад холбогч жишиг үзүүлэлтүүдийг ажиллуулцгаая:

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
Таны харж байгаагаар үр дүн нь асинхрон өргөтгөлтэй харьцуулахад илүү дээр юм (2 процесс дээр ажиллаж байгаа Swoole-г тооцохгүй). PECL холбогчийн хувьд Update болон Upsert үйлдлүүд хоосон гэдгийг анхаарна уу. Энэ нь эдгээр үйлдлүүд алдаатай бүтэлгүйтсэнтэй холбоотой - энэ нь параллель, экс-tarantool эсвэл хоёулангийнх нь буруу байсан эсэхийг би мэдэхгүй.

Одоо SQL-ийн гүйцэтгэлийг харьцуулъя:

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна
Синхроноор ажилладаг холбогчдод зориулсан графиктай ижил төстэй байдлыг анзаарсан уу?

Хамтдаа

Эцэст нь туршиж үзсэн өргөтгөлүүдийн ерөнхий дүр зургийг харахын тулд бүх үр дүнг нэг графикаар нэгтгэн харуулъя. График дээр хараахан хийж амжаагүй ганцхан шинэ тест нэмж оруулъя - Async coroutines-ийг Parallel* ашиглан зэрэгцээ ажиллуулцгаая. Дээрх өргөтгөлүүдийг нэгтгэх санаа аль хэдийн бий болсон хэлэлцсэн зохиогчид, гэхдээ зөвшилцөлд хүрээгүй тул та өөрөө хийх хэрэгтэй болно.

* Swoole coroutines-ийг Parallel-тэй ажиллуулах боломжгүй байсан тул эдгээр өргөтгөлүүд нь таарахгүй байна.

Тиймээс эцсийн үр дүн:

Async, Swoole болон Parallel ашиглан Tarantool-д зориулсан PHP холбогчийг хурдасгаж байна

Оронд дүгнэлтийг

Миний бодлоор үр дүн нь үнэ цэнэтэй байсан бөгөөд зарим шалтгааны улмаас энэ нь хязгаар биш гэдэгт би итгэлтэй байна! Үүнийг зөвхөн өөртөө зориулж бодит төсөл дээр шийдэх шаардлагатай эсэхээс үл хамааран энэ нь миний хувьд синхрон TCP холбогчоос хэр их хүчин чармайлт гаргаж "шахаж" болохыг үнэлэх боломжийг олгодог сонирхолтой туршилт байсан гэж би хэлэх болно. Хэрэв танд жишиг үзүүлэлтүүдийг сайжруулах санаа байгаа бол би таны татах хүсэлтийг авч үзэхэд таатай байх болно. Эхлэх заавар, үр дүн бүхий бүх кодыг тусад нь нийтэлсэн агуулахууд.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх