प्रोहोस्टर > Блог > प्रशासन > Async, Swoole आणि Parallel वापरून Tarantool साठी PHP कनेक्टरला गती देणे
Async, Swoole आणि Parallel वापरून Tarantool साठी PHP कनेक्टरला गती देणे
В экосистеме PHP на данный момент существует два коннектора для работы с сервером Tarantool ― это официальное расширение PECL tarantool/tarantool-php, C मध्ये लिहिलेले, आणि tarantool-php/client, написанный на PHP. Я являюсь автором последнего.
या लेखात, मी दोन्ही लायब्ररींच्या कार्यप्रदर्शन चाचणीचे परिणाम सामायिक करू इच्छितो आणि कोडमध्ये कमीत कमी बदल करून, आपण 3-5 कामगिरी वाढ कशी मिळवू शकता हे दर्शवू इच्छितो (सिंथेटिक चाचण्यांवर!).
आम्ही काय चाचणी करू?
आम्ही वर नमूद केलेल्यांची चाचणी करू समकालिक असिंक्रोनस, समांतर आणि असिंक्रोनस-समांतरपणे चालणारे कनेक्टर. 🙂 आम्ही स्वतः कनेक्टरच्या कोडला देखील स्पर्श करू इच्छित नाही. तुम्हाला हवे ते साध्य करण्यासाठी सध्या अनेक विस्तार उपलब्ध आहेत:
स्वूले - PHP साठी उच्च-कार्यक्षमता असिंक्रोनस फ्रेमवर्क. Alibaba आणि Baidu सारख्या इंटरनेट दिग्गजांनी वापरले. आवृत्ती ४.१.० पासून एक जादूची पद्धत दिसून आली 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 = काहीही नाही) आणि वाढलेले नेटवर्क बफर (readahead = 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 ट्युपल्सने भरली जाते.
{id, "tuplе_<id>"}
Доступ к кортежам осуществляется по рандомному значению ключа.
बेंचमार्क स्वतः सर्व्हरला एकच विनंती आहे, जी 10,000 वेळा अंमलात आणली जाते (क्रांती), जी यामधून, पुनरावृत्तीमध्ये अंमलात आणली जाते. 5 पुनरावृत्त्यांमधील सर्व वेळ विचलन 3%* च्या स्वीकार्य त्रुटीमध्ये होईपर्यंत पुनरावृत्ती पुनरावृत्ती केली जाते. यानंतर, सरासरी निकाल घेतला जातो. प्रोसेसरला थ्रोटल होण्यापासून रोखण्यासाठी पुनरावृत्ती दरम्यान 1 सेकंदाचा विराम आहे. लुआचा कचरा गोळा करणारा प्रत्येक पुनरावृत्तीपूर्वी अक्षम केला जातो आणि तो पूर्ण झाल्यानंतर सुरू करण्यास भाग पाडले जाते. PHP प्रक्रिया केवळ बेंचमार्कसाठी आवश्यक असलेल्या विस्तारांसह लॉन्च केली जाते, आउटपुट बफरिंग सक्षम केले जाते आणि कचरा गोळा करणारे अक्षम केले जाते.
* क्रांतीची संख्या, पुनरावृत्ती आणि त्रुटी थ्रेशोल्ड बेंचमार्क सेटिंग्जमध्ये बदलले जाऊ शकतात.
चाचणी वातावरण
खाली प्रकाशित केलेले परिणाम MacBookPro (2015), ऑपरेटिंग सिस्टीम - Fedora 30 (kernel version 5.3.8-200.fc30.x86_64) वर केले गेले. टॅरंटूल पॅरामीटरसह डॉकरमध्ये लॉन्च केले गेले.--network host".
* दुर्दैवाने, अधिकृत कनेक्टर PHP आवृत्ती > 7.2 सह कार्य करत नाही. PHP 7.3 वर विस्तार संकलित आणि चालविण्यासाठी, मला वापरावे लागले पॅच.
निकाल
सिंक्रोनस मोड
टारनटूल प्रोटोकॉल बायनरी फॉरमॅट वापरतो मेसेजपॅक для сериализации сообщений. В коннекторе PECL сериализация скрыта глубоко в недрах библиотеки и повлиять на процесс кодирования из userland-кода शक्य वाटत नाही. एक शुद्ध PHP कनेक्टर, त्याउलट, मानक एन्कोडरचा विस्तार करून किंवा आपल्या स्वतःच्या अंमलबजावणीचा वापर करून एन्कोडिंग प्रक्रिया सानुकूलित करण्याची क्षमता प्रदान करते. बॉक्सच्या बाहेर दोन एन्कोडर उपलब्ध आहेत, एक त्यावर आधारित आहे msgpack/msgpack-php (अधिकृत MessagePack PECL विस्तार), दुसरा चालू आहे rybakit/msgpack (शुद्ध PHP मध्ये).
कनेक्टर्सची तुलना करण्यापूर्वी, आम्ही PHP कनेक्टरसाठी MessagePack एन्कोडरचे कार्यप्रदर्शन मोजू आणि पुढील चाचण्यांमध्ये आम्ही सर्वोत्तम परिणाम दर्शविणारा एक वापरू:
जरी PHP आवृत्ती (शुद्ध) वेगात पीईसीएल विस्तारापेक्षा निकृष्ट आहे, तरीही वास्तविक प्रकल्पांमध्ये मी ते वापरण्याची शिफारस करतो rybakit/msgpack, потому как в официальном расширении MessagePack спецификация формата реализована лишь частично (например, нет поддержки пользовательских типов данных, без которой вы не сможете использовать Decimal — новый тип данных, представленный в Tarantool 2.3) и имеет ряд других समस्या (PHP 7.4 सह सुसंगतता समस्यांसह). बरं, सर्वसाधारणपणे, प्रकल्प बेबंद दिसतो.
तर, सिंक्रोनस मोडमध्ये कनेक्टर्सचे कार्यप्रदर्शन मोजूया:
आलेखावरून पाहिल्याप्रमाणे, PECL कनेक्टर (Tarantool) PHP कनेक्टर (क्लायंट) च्या तुलनेत चांगली कामगिरी दाखवते. परंतु हे आश्चर्यकारक नाही, कारण नंतरचे, हळूवार भाषेत अंमलात आणण्याव्यतिरिक्त, प्रत्यक्षात अधिक कार्य करते: प्रत्येक कॉलसह एक नवीन ऑब्जेक्ट तयार केला जातो. विनंती и प्रतिसाद (सिलेक्टच्या बाबतीत - देखील मापदंड, आणि अपडेट/अप्सर्टच्या बाबतीत - ऑपरेशन), отдельные сущности कनेक्शन, पॅकर и हँडलर ते ओव्हरहेड देखील जोडतात. अर्थात, लवचिकता किंमतीला येते. तथापि, सर्वसाधारणपणे, PHP दुभाषी चांगले कार्यप्रदर्शन दर्शविते, जरी फरक आहे, तो क्षुल्लक आहे आणि, कदाचित, PHP 7.4 मध्ये प्रीलोडिंग वापरताना आणखी कमी असेल, PHP 8 मध्ये JIT चा उल्लेख न करता.
चला पुढे जाऊया. Tarantool 2.0 ने SQL साठी समर्थन जोडले. चला एसक्यूएल प्रोटोकॉल वापरून सिलेक्ट, इन्सर्ट, अपडेट आणि डिलीट ऑपरेशन्स करण्याचा प्रयत्न करूया आणि परिणामांची तुलना noSQL (बायनरी) समकक्षांसह करूया:
एसक्यूएल परिणाम फार प्रभावी नाहीत (मी तुम्हाला आठवण करून देतो की आम्ही अद्याप सिंक्रोनस मोडची चाचणी घेत आहोत). तथापि, मी वेळेपूर्वी याबद्दल नाराज होणार नाही; SQL समर्थन अद्याप सक्रिय विकासाधीन आहे (तुलनेने अलीकडे, उदाहरणार्थ, समर्थन जोडले गेले. prepared statements) आणि, यादीनुसार न्याय करणे समस्या, SQL इंजिनला भविष्यात अनेक ऑप्टिमायझेशन केले जातील.
एसिंक
बरं, आता Async विस्तार आम्हाला वरील परिणाम सुधारण्यात कशी मदत करू शकतो ते पाहू. असिंक्रोनस प्रोग्राम्स लिहिण्यासाठी, विस्तार कोराउटिनवर आधारित API प्रदान करतो, ज्याचा आम्ही वापर करू. आम्हाला प्रायोगिकरित्या आढळून आले की आमच्या पर्यावरणासाठी कॉरोटिनची इष्टतम संख्या 25 आहे:
10,000 कोरोटीनमध्ये 25 ऑपरेशन्स “पसरवा” आणि काय होते ते पहा:
Печально, но коннектор PECL не запустился с ext-async.
А что c SQL?
Как видите, в асинхронном режиме разница между бинарным протоколом и SQL стала в пределах погрешности.
स्वूले
Опять выясняем оптимальное количество корутин, теперь уже для Swoole:
चला 25 वाजता थांबूया. Async विस्ताराप्रमाणेच तीच युक्ती पुन्हा करूया - 10,000 ऑपरेशन्स 25 coroutines मध्ये वितरित करा. याव्यतिरिक्त, आम्ही आणखी एक चाचणी जोडू ज्यामध्ये आम्ही सर्व काम 2 दोन प्रक्रियांमध्ये विभागू (म्हणजे, प्रत्येक प्रक्रिया 5,000 कोरोटिनमध्ये 25 ऑपरेशन्स करेल). वापरून प्रक्रिया तयार केल्या जातील SwooleProcess.
परिणाम:
Swole एक प्रक्रिया चालवताना Async च्या तुलनेत थोडा कमी परिणाम दर्शवितो, परंतु 2 प्रक्रियेसह चित्र नाटकीयरित्या बदलते (क्रमांक 2 योगायोगाने निवडला गेला नाही; माझ्या मशीनवर, ती 2 प्रक्रिया होती ज्यांनी सर्वोत्तम परिणाम दर्शविला).
तसे, प्रक्रियांसह कार्य करण्यासाठी Async विस्तारामध्ये API देखील आहे, परंतु तेथे मला एक किंवा अधिक प्रक्रियांमध्ये बेंचमार्क चालविण्यापासून कोणताही फरक दिसला नाही (मी कुठेतरी गोंधळ केला असण्याची शक्यता आहे).
एसक्यूएल वि बायनरी प्रोटोकॉल:
Async प्रमाणे, बायनरी आणि SQL ऑपरेशन्समधील फरक एसिंक्रोनस मोडमध्ये काढून टाकला जातो.
समांतर
पॅरलल एक्स्टेंशन हे कोरोटीन बद्दल नसून थ्रेड्स बद्दल असल्याने, समांतर थ्रेड्सची इष्टतम संख्या मोजूया:
माझ्या मशीनवर ते 16 आहे. 16 समांतर थ्रेड्सवर कनेक्टर बेंचमार्क चालवू:
Как видите, результат даже лучше, чем с асинхронными расширениями (не считая Swoole запущенном на 2 процессах). Заметьте, что для коннектора PECL на месте Update и Upsert операций пусто. Связано это с тем, что данные операции вылетели с ошибкой ― не знаю, по вине ext-parallel, ext-tarantool или обоих.
Теперь сравним производительность SQL:
समकालिकपणे चालणार्या कनेक्टरसाठी आलेखाशी समानता लक्षात घ्या?
एकत्र
आणि शेवटी, चाचणी केलेल्या विस्तारांसाठी एकंदर चित्र पाहण्यासाठी एका आलेखामध्ये सर्व परिणामांचा सारांश घेऊ. चला चार्टमध्ये फक्त एक नवीन चाचणी जोडूया, जी आम्ही अद्याप केली नाही - समांतर* वापरून समांतर Async coroutines चालवू. वरील विस्तार समाकलित करण्याची कल्पना आधीपासूनच आहे चर्चा झाली लेखक, परंतु कोणतेही एकमत झाले नाही, तुम्हाला ते स्वतः करावे लागेल.
* समांतर सह Swoole coroutines लाँच करणे शक्य नव्हते; असे दिसते की हे विस्तार विसंगत आहेत.
तर, अंतिम परिणाम:
त्याऐवजी एक निष्कर्ष
माझ्या मते, परिणाम अगदी योग्य असल्याचे दिसून आले आणि काही कारणास्तव मला खात्री आहे की ही मर्यादा नाही! तुम्हाला हे प्रत्यक्ष प्रकल्पात केवळ तुमच्यासाठीच ठरवायचे आहे की नाही, मी फक्त एवढेच म्हणेन की माझ्यासाठी हा एक मनोरंजक प्रयोग होता जो तुम्हाला सिंक्रोनस TCP कनेक्टरमधून कमीत कमी प्रयत्नात किती "पिळून" काढू शकतो याचे मूल्यांकन करू देतो. जर तुमच्याकडे बेंचमार्क सुधारण्याच्या कल्पना असतील, तर मला तुमच्या पुल विनंतीवर विचार करण्यात आनंद होईल. प्रक्षेपण सूचना आणि परिणामांसह सर्व कोड स्वतंत्रपणे प्रकाशित केले आहेत भांडार.