Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi

PHP ekosistemində hazırda Tarantool serveri ilə işləmək üçün iki bağlayıcı var - bu, rəsmi PECL uzantısıdır. tarantool/tarantool-php, C ilə yazılmış və tarantool-php/client, PHP-də yazılmışdır. Sonuncunun müəllifi mənəm.

Bu yazıda hər iki kitabxananın performans testinin nəticələrini bölüşmək və koda minimal dəyişikliklərlə 3-5 performans artımına necə nail ola biləcəyinizi göstərmək istərdim (sintetik testlərdə!).

Nəyi sınayacağıq?

Yuxarıda qeyd olunanları sınaqdan keçirəcəyik sinxron asinxron, paralel və asinxron-paralel işləyən birləşdiricilər. 🙂 Biz də birləşdiricilərin koduna toxunmaq istəmirik. İstədiyinizə nail olmaq üçün hazırda bir neçə uzantı mövcuddur:

  • Swoole ― PHP üçün yüksək performanslı asinxron çərçivə. Alibaba və Baidu kimi internet nəhəngləri tərəfindən istifadə olunur. 4.1.0 versiyasından bəri sehrli bir üsul ortaya çıxdı SwooleRuntime::enableCoroutine(), bu sizə “bir kod sətri ilə sinxron PHP şəbəkə kitabxanalarını asinxron olanlara çevirməyə” imkan verir.
  • Async yaxın vaxtlara qədər PHP-də asinxron iş üçün çox perspektivli genişlənmə idi. Niyə bu yaxınlara qədər? Təəssüf ki, mənə məlum olmayan səbəbə görə müəllif anbarı sildi və layihənin gələcək taleyi bəlli deyil. Mən istifadə etməliyəm bir çəngəllərdən. Swoole kimi, bu genişləndirmə TCP və TLS axınlarının standart tətbiqini asinxron versiyaları ilə əvəz etməklə asinxroniyanı aktivləşdirmək üçün bilək hərəkəti ilə şalvarınızı asanlıqla açmağa imkan verir. Bu, " seçimi ilə edilirasync.tcp = 1".
  • Paralel ― phpdbg, apcu, pthreads, pcov, uopz kimi kitabxanaların müəllifi olan tanınmış Joe Watkins-dən kifayət qədər yeni genişləndirmə. Artırma PHP-də çox iş parçacığı üçün API təmin edir və pthreads üçün əvəzedici kimi yerləşdirilir. Kitabxananın əhəmiyyətli bir məhdudiyyəti onun yalnız PHP-nin ZTS (Zend Thread Safe) versiyası ilə işləməsidir.

Necə sınaqdan keçirəcəyik?

Gəlin qabaqcadan yazma qeydi deaktiv edilmiş Tarantool nümunəsini işə salaq (wal_rejimi = heç biri) və artan şəbəkə buferi (qabaqcadan oxumaq = 1 * 1024 * 1024). Birinci seçim disklə işi aradan qaldıracaq, ikincisi əməliyyat sisteminin buferindən daha çox sorğu oxumağa imkan verəcək və bununla da sistem zənglərinin sayını minimuma endirəcək.

Verilənlərlə işləyən meyarlar üçün (daxiletmə, silmə, oxuma və s.) etalon işə başlamazdan əvvəl memtx boşluğu (yenidən) yaradılacaq ki, burada əsas indeks dəyərləri sifarişli tam ədədlərin generatoru tərəfindən yaradılır. (ardıcıllıq).
Boş DDL belə görünür:

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

Lazım gələrsə, etalon işə başlamazdan əvvəl boşluq formanın 10,000 tuple ilə doldurulur.

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

Tuples təsadüfi açar dəyərindən istifadə etməklə əldə edilir.

Bençmarkın özü 10,000 dəfə yerinə yetirilən (inqilablar) serverə tək sorğudur, bu da öz növbəsində iterasiyalarda yerinə yetirilir. 5 iterasiya arasındakı bütün vaxt sapmaları 3%* məqbul xəta daxilində olana qədər təkrarlamalar təkrarlanır. Bundan sonra orta nəticə alınır. Prosessorun tıxanmasının qarşısını almaq üçün təkrarlamalar arasında 1 saniyəlik fasilə verilir. Luanın zibil toplayıcısı hər iterasiyadan əvvəl söndürülür və tamamlandıqdan sonra işə başlamağa məcbur olur. PHP prosesi yalnız benchmark üçün lazım olan genişləndirmələrlə işə salınır, çıxış buferləşdirilməsi aktivləşdirilir və zibil toplayıcısı qeyri-aktiv edilir.

* İnqilabların, iterasiyaların və səhv həddi müqayisə parametrlərində dəyişdirilə bilər.

Test mühiti

Aşağıda dərc edilmiş nəticələr MacBookPro (2015), əməliyyat sistemi - Fedora 30 (kernel versiyası 5.3.8-200.fc30.x86_64) üzərində hazırlanmışdır. Tarantool docker-də "parametri ilə işə salındı.--network host".

Paket versiyaları:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, a872fc2f86 qurun
PHP: 7.3.11 (cli) (quruldu: 22 oktyabr 2019-cu il 08:11:04)
tarantool/müştəri: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ 7.3 üçün yamaq)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swoole: 4.4.12
xarici paralel: 1.1.3

* Təəssüf ki, rəsmi konnektor PHP versiyası > 7.2 ilə işləmir. Genişlənməni PHP 7.3-də tərtib etmək və işə salmaq üçün istifadə etməli oldum yamaq.

Tapıntılar

Sinxron rejim

Tarantool protokolu ikili formatdan istifadə edir Mesaj Paketi mesajları seriallaşdırmaq üçün. PECL konnektorunda seriallaşdırma kitabxananın dərinliklərində gizlənir və istifadəçi kodundan kodlaşdırma prosesinə təsir göstərir. mümkün görünmür. Təmiz PHP konnektoru, əksinə, standart kodlayıcını genişləndirməklə və ya öz tətbiqinizdən istifadə etməklə kodlaşdırma prosesini fərdiləşdirmək imkanı verir. Qutudan çıxarılan iki kodlayıcı var, biri bunlara əsaslanır msgpack/msgpack-php (rəsmi MessagePack PECL genişləndirilməsi), digəri aktivdir rybakit/msgpack (saf PHP-də).

Bağlayıcıları müqayisə etməzdən əvvəl biz PHP konnektoru üçün MessagePack kodlayıcılarının işini ölçəcəyik və sonrakı sınaqlarda ən yaxşı nəticəni göstərəndən istifadə edəcəyik:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
PHP versiyası (Pure) sürət baxımından PECL genişlənməsindən aşağı olsa da, real layihələrdə hələ də ondan istifadə etməyi tövsiyə edərdim. rybakit/msgpack, çünki rəsmi MessagePack genişləndirməsində format spesifikasiyası yalnız qismən həyata keçirilir (məsələn, fərdi məlumat növləri üçün heç bir dəstək yoxdur, onsuz siz Ondalıqdan istifadə edə bilməyəcəksiniz - Tarantool 2.3-də təqdim olunan yeni məlumat növü) və başqalarının sayı problemlər (PHP 7.4 ilə uyğunluq problemləri də daxil olmaqla). Ümumiyyətlə, layihə tərk edilmiş görünür.

Beləliklə, sinxron rejimdə birləşdiricilərin işini ölçək:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
Qrafikdən göründüyü kimi, PECL konnektoru (Tarantool) PHP konnektoru (Client) ilə müqayisədə daha yaxşı performans göstərir. Ancaq bu təəccüblü deyil, nəzərə alsaq ki, sonuncu daha yavaş bir dildə həyata keçirilməklə yanaşı, əslində daha çox iş görür: hər zənglə yeni bir obyekt yaradılır. tələb и Cavab (Seçmə vəziyyətində - həmçinin Meyarları, və Yeniləmə/Upsert vəziyyətində ― Əməliyyatlar), ayrı-ayrı qurumlar DeBloc | XNUMX + On,es, Packer и İşləyən onlar da əlavə xərclər əlavə edirlər. Aydındır ki, çeviklik bir qiymətə gəlir. Lakin, ümumiyyətlə, PHP tərcüməçisi yaxşı performans göstərir, fərq olsa da, əhəmiyyətsizdir və PHP 7.4-də JIT-i demirik, PHP 8-də əvvəlcədən yükləmədən istifadə edərkən, bəlkə də daha az olacaq.

Gəlin davam edək. Tarantool 2.0 SQL üçün dəstək əlavə etdi. SQL protokolundan istifadə edərək Select, Insert, Update və Delete əməliyyatlarını yerinə yetirməyə çalışaq və nəticələri noSQL (ikili) ekvivalentləri ilə müqayisə edək:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
SQL nəticələri çox təsir edici deyil (xatırlatmaq istəyirəm ki, biz hələ də sinxron rejimi sınaqdan keçiririk). Bununla belə, əvvəlcədən buna görə üzülməzdim; SQL dəstəyi hələ də aktiv inkişaf mərhələsindədir (nisbətən yaxınlarda, məsələn, dəstək əlavə edildi bəyanatlar hazırlamışdır) və siyahıya əsasən məsələlər, SQL mühərriki gələcəkdə bir sıra optimallaşdırmalardan keçəcək.

Asınc

Yaxşı, indi Async genişləndirilməsinin yuxarıdakı nəticələri yaxşılaşdırmaqda bizə necə kömək edə biləcəyinə baxaq. Asinxron proqramları yazmaq üçün genişləndirmə bizim istifadə edəcəyimiz koroutinlərə əsaslanan API təmin edir. Təcrübə ilə müəyyən edirik ki, ətraf mühitimiz üçün optimal koroutin sayı 25-dir:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
10,000 əməliyyatı 25 korutin üzrə "yayın" və nə baş verdiyinə baxın:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
üçün saniyədə əməliyyatların sayı 3 dəfədən çox artdı tarantool-php/client!

Təəssüf ki, PECL konnektoru ext-async ilə başlamadı.

Bəs SQL?

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
Gördüyünüz kimi, asinxron rejimdə binar protokol ilə SQL arasındakı fərq xəta həddinə çatdı.

Swoole

Yenə də bu dəfə Swoole üçün optimal koroutin sayını tapırıq:
Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
Gəlin 25-də dayanaq. Gəlin Async genişlənməsi ilə eyni hiyləni təkrarlayaq - 10,000 koroutin arasında 25 əməliyyat paylayın. Bundan əlavə, biz bütün işləri 2 iki prosesə ayıracağımız başqa bir test əlavə edəcəyik (yəni hər bir proses 5,000 korutində 25 əməliyyat yerinə yetirəcək). Proseslər istifadə edərək yaradılacaq SwooleProcess.

Nəticələr:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
Swole bir prosesdə işlədildikdə Async ilə müqayisədə bir qədər aşağı nəticə göstərir, lakin 2 proseslə şəkil kəskin şəkildə dəyişir (2 rəqəmi təsadüfən seçilməyib; mənim maşınımda ən yaxşı nəticəni göstərən 2 proses olub).

Yeri gəlmişkən, Async uzantısında proseslərlə işləmək üçün bir API də var, amma orada bir və ya bir neçə prosesdə etalonların işləməsindən heç bir fərq görmədim (haradasa səhv etmişəm).

SQL və ikili protokol:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
Async-də olduğu kimi, ikili və SQL əməliyyatları arasındakı fərq asinxron rejimdə aradan qaldırılır.

Paralel

Paralel uzantı koroutinlər haqqında deyil, iplər haqqında olduğundan, paralel iplərin optimal sayını ölçək:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
Mənim maşınımda 16-ya bərabərdir. 16 paralel ipdə birləşdirici meyarları yerinə yetirək:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
Gördüyünüz kimi, nəticə asinxron uzantılardan daha yaxşıdır (2 prosesdə işləyən Swoole nəzərə alınmır). Nəzərə alın ki, PECL konnektoru üçün Update və Upsert əməliyyatları boşdur. Bu, bu əməliyyatların xəta ilə uğursuz olması ilə bağlıdır - bunun ek-paralel, ek-tarantool və ya hər ikisinin günahı olub olmadığını bilmirəm.

İndi SQL performansını müqayisə edək:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi
Sinxron işləyən birləşdiricilər üçün qrafiklə oxşarlığa diqqət yetirin?

Birlikdə

Və nəhayət, sınaqdan keçirilmiş genişləndirmələr üçün ümumi mənzərəni görmək üçün bütün nəticələri bir qrafikdə ümumiləşdirək. Qrafikə hələ etmədiyimiz bir yeni test əlavə edək - Parallel* istifadə edərək paralel olaraq Async koroutinləri işlədək. Yuxarıdakı uzantıların inteqrasiyası ideyası artıq mövcuddur müzakirə edildi müəlliflər, lakin konsensus əldə edilmədi, bunu özünüz etməli olacaqsınız.

* Parallel ilə Swoole koroutinlərini işə salmaq mümkün olmadı; görünür, bu uzantılar uyğun gəlmir.

Beləliklə, yekun nəticələr:

Async, Swoole və Parallel istifadə edərək Tarantool üçün PHP konnektorlarının sürətləndirilməsi

Bunun əvəzinə bir nəticəyə

Məncə, nəticələr olduqca layiqli oldu və nədənsə əminəm ki, bu hədd deyil! Bunu yalnız özünüz üçün real bir layihədə qərar verməyiniz lazım olub-olmamasından asılı olmayaraq, yalnız deyim ki, mənim üçün bu, sinxron TCP konnektorundan minimum səylə nə qədər "sıxıb çıxara" biləcəyinizi qiymətləndirməyə imkan verən maraqlı bir təcrübə idi. Qiymətləndirmələri təkmilləşdirmək üçün fikirləriniz varsa, mən sizin çəkmə sorğunuzu nəzərdən keçirməkdən məmnun olaram. Başlama təlimatları və nəticələri olan bütün kodlar ayrıca dərc olunur depolar.

Mənbə: www.habr.com

Добавить комментарий