PHP экосистемд одоогоор Tarantool сервертэй ажиллах хоёр холбогч байгаа бөгөөд энэ нь албан ёсны PECL өргөтгөл юм.
Энэ нийтлэлд би хоёр номын сангийн гүйцэтгэлийн туршилтын үр дүнг хуваалцаж, кодын хамгийн бага өөрчлөлтөөр та гүйцэтгэлийг 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 протокол нь хоёртын форматыг ашигладаг
Холбогчдыг харьцуулахын өмнө бид PHP холбогчдод зориулсан MessagePack кодлогчийн гүйцэтгэлийг хэмжиж, цаашдын туршилтуудад хамгийн сайн үр дүнг харуулсаныг ашиглана.
Хэдийгээр PHP хувилбар (Цэвэр) нь хурдны хувьд PECL өргөтгөлөөс доогуур боловч бодит төслүүдэд үүнийг ашиглахыг зөвлөж байна.
Тиймээс синхрон горимд холбогчдын гүйцэтгэлийг хэмжье.
Графикаас харахад PECL холбогч (Tarantool) нь PHP холбогч (Клиент) -тэй харьцуулахад илүү сайн гүйцэтгэлтэй байгааг харуулж байна. Гэхдээ энэ нь удаан хэлээр хэрэгжихээс гадна илүү их ажил хийдэг тул энэ нь гайхмаар зүйл биш юм: дуудлага болгонд шинэ объект үүсдэг. авагч и хариу арга хэмжээ (сонгосон тохиолдолд - мөн Шалгуур, мөн Шинэчлэх/Дээш оруулах тохиолдолд ― үйл ажиллагаа), тусдаа аж ахуйн нэгжүүд Холболтын, Пакер и Зохицуулагч Тэд мөн нэмэлт зардлыг нэмдэг. Мэдээжийн хэрэг, уян хатан байдал нь үнэтэй байдаг. Гэсэн хэдий ч ерөнхийдөө PHP орчуулагч нь сайн гүйцэтгэлийг харуулдаг, гэхдээ ялгаа байгаа ч энэ нь ач холбогдолгүй бөгөөд PHP 7.4 дээр урьдчилан ачаалах үед PHP 8 дээр JIT-ийг дурдахгүй байх нь бүр ч бага байх болно.
Үргэлжлүүлье. Tarantool 2.0 нь SQL-ийн дэмжлэгийг нэмсэн. Сонгох, оруулах, шинэчлэх, устгах үйлдлүүдийг SQL протокол ашиглан хийж, үр дүнг noSQL (хоёртын) эквиваленттай харьцуулж үзье.
SQL-ийн үр дүн тийм ч гайхалтай биш байна (бид синхрон горимыг туршиж байгаа гэдгийг танд сануулъя). Гэсэн хэдий ч би үүнд урьдчилж бухимдахгүй байх байсан; SQL дэмжлэг идэвхтэй хөгжиж байгаа хэвээр байна (харьцангуй саяхан, жишээ нь дэмжлэг нэмэгдсэн байна.
Асинк
За, одоо Async өргөтгөл нь дээрх үр дүнг сайжруулахад хэрхэн тусалж болохыг харцгаая. Асинхрон программ бичихийн тулд өргөтгөл нь coroutines дээр суурилсан API-г өгдөг бөгөөд үүнийг бидний ашиглах болно. Бидний хүрээлэн буй орчны хамгийн оновчтой тоо нь 25 гэдгийг бид эмпирик байдлаар олж мэдсэн.
10,000 корутинд 25 үйлдлийг "тархаж", юу болохыг хараарай:
секундэд хийх үйлдлийн тоо 3 дахин нэмэгджээ
Харамсалтай нь PECL холбогч нь ext-async-ээр эхлээгүй байна.
SQL-ийн талаар юу хэлэх вэ?
Таны харж байгаагаар асинхрон горимд хоёртын протокол ба SQL-ийн ялгаа нь алдааны хязгаарт хүрсэн байна.
Swoole
Энэ удаад Свулийн хувьд бид корутинуудын оновчтой тоог дахин олж мэдэв.
25 дээр зогсооцгооё. Async өргөтгөлтэй адил трик давтъя - 10,000 корутин хооронд 25 үйлдлийг хуваарил. Нэмж дурдахад бид бүх ажлыг 2 хоёр процесст хуваах өөр нэг тестийг нэмж оруулах болно (өөрөөр хэлбэл процесс бүр 5,000 корутинд 25 үйлдлийг гүйцэтгэх болно). Процессуудыг ашиглан үүсгэнэ SwooleProcess.
Үр дүн:
Swole нь нэг процесс дээр ажиллахад Async-тэй харьцуулахад арай бага үр дүнг харуулдаг боловч 2 процесст зураг эрс өөрчлөгддөг (2-ын тоог санамсаргүй байдлаар сонгоогүй; миний машин дээр 2 процесс хамгийн сайн үр дүнг харуулсан).
Дашрамд хэлэхэд, Async өргөтгөл нь процессуудтай ажиллах API-тай боловч тэнд би нэг буюу хэд хэдэн процесст жишиг тогтоохоос ямар ч ялгааг анзаараагүй (би хаа нэгтээ будлиулсан байж магадгүй).
SQL болон хоёртын протокол:
Async-ийн нэгэн адил хоёртын болон SQL үйлдлийн хоорондын ялгаа асинхрон горимд арилдаг.
Зэрэгцээ
Зэрэгцээ өргөтгөл нь корутинуудын тухай биш, харин утаснуудын тухай тул зэрэгцээ утаснуудын оновчтой тоог хэмжье.
Энэ нь миний машин дээр 16-тай тэнцүү байна. 16 зэрэгцээ утаснуудад холбогч жишиг үзүүлэлтүүдийг ажиллуулцгаая:
Таны харж байгаагаар үр дүн нь асинхрон өргөтгөлтэй харьцуулахад илүү дээр юм (2 процесс дээр ажиллаж байгаа Swoole-г тооцохгүй). PECL холбогчийн хувьд Update болон Upsert үйлдлүүд хоосон гэдгийг анхаарна уу. Энэ нь эдгээр үйлдлүүд алдаатай бүтэлгүйтсэнтэй холбоотой - энэ нь параллель, экс-tarantool эсвэл хоёулангийнх нь буруу байсан эсэхийг би мэдэхгүй.
Одоо SQL-ийн гүйцэтгэлийг харьцуулъя:
Синхроноор ажилладаг холбогчдод зориулсан графиктай ижил төстэй байдлыг анзаарсан уу?
Хамтдаа
Эцэст нь туршиж үзсэн өргөтгөлүүдийн ерөнхий дүр зургийг харахын тулд бүх үр дүнг нэг графикаар нэгтгэн харуулъя. График дээр хараахан хийж амжаагүй ганцхан шинэ тест нэмж оруулъя - Async coroutines-ийг Parallel* ашиглан зэрэгцээ ажиллуулцгаая. Дээрх өргөтгөлүүдийг нэгтгэх санаа аль хэдийн бий болсон
* Swoole coroutines-ийг Parallel-тэй ажиллуулах боломжгүй байсан тул эдгээр өргөтгөлүүд нь таарахгүй байна.
Тиймээс эцсийн үр дүн:
Оронд дүгнэлтийг
Миний бодлоор үр дүн нь үнэ цэнэтэй байсан бөгөөд зарим шалтгааны улмаас энэ нь хязгаар биш гэдэгт би итгэлтэй байна! Үүнийг зөвхөн өөртөө зориулж бодит төсөл дээр шийдэх шаардлагатай эсэхээс үл хамааран энэ нь миний хувьд синхрон TCP холбогчоос хэр их хүчин чармайлт гаргаж "шахаж" болохыг үнэлэх боломжийг олгодог сонирхолтой туршилт байсан гэж би хэлэх болно. Хэрэв танд жишиг үзүүлэлтүүдийг сайжруулах санаа байгаа бол би таны татах хүсэлтийг авч үзэхэд таатай байх болно. Эхлэх заавар, үр дүн бүхий бүх кодыг тусад нь нийтэлсэн
Эх сурвалж: www.habr.com