Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel

Dalam ekosistem PHP pada masa ini terdapat dua penyambung untuk bekerja dengan pelayan Tarantool - ini adalah sambungan PECL rasmi tarantool/tarantool-php, ditulis dalam C, dan tarantool-php/client, ditulis dalam PHP. Saya adalah pengarang yang terakhir.

Dalam artikel ini, saya ingin berkongsi hasil ujian prestasi kedua-dua perpustakaan dan menunjukkan bagaimana, dengan perubahan minimum pada kod, anda boleh mencapai peningkatan prestasi 3-5 (pada ujian sintetik!).

Apa yang akan kita uji?

Kami akan menguji yang disebutkan di atas segerak penyambung berjalan secara tak segerak, selari, dan selari tak segerak. πŸ™‚ Kami juga tidak mahu menyentuh kod penyambung itu sendiri. Pada masa ini terdapat beberapa sambungan yang tersedia untuk mencapai perkara yang anda inginkan:

  • Swooole ― rangka kerja tak segerak berprestasi tinggi untuk PHP. Digunakan oleh gergasi Internet seperti Alibaba dan Baidu. Sejak versi 4.1.0 kaedah ajaib telah muncul SwooleRuntime::enableCoroutine(), yang membolehkan anda "menukar perpustakaan rangkaian PHP segerak kepada tidak segerak dengan satu baris kod."
  • Async sehingga baru-baru ini merupakan sambungan yang sangat menjanjikan untuk kerja tak segerak dalam PHP. Mengapa sehingga baru-baru ini? Malangnya, atas sebab yang tidak saya ketahui, penulis memadamkan repositori dan nasib masa depan projek itu tidak jelas. Saya perlu menggunakannya 1 daripada garpu. Seperti Swoole, sambungan ini membolehkan anda menghidupkan seluar anda dengan mudah dengan jentikan pergelangan tangan untuk mendayakan tak segerak dengan menggantikan pelaksanaan standard strim TCP dan TLS dengan versi tak segeraknya. Ini dilakukan melalui pilihan "async.tcp = 1".
  • Selari ― sambungan yang agak baharu daripada Joe Watkins yang terkenal, pengarang perpustakaan seperti phpdbg, apcu, pthreads, pcov, uopz. Sambungan ini menyediakan API untuk multithreading dalam PHP dan diletakkan sebagai pengganti pthreads. Batasan ketara perpustakaan ialah ia hanya berfungsi dengan versi PHP ZTS (Zend Thread Safe).

Bagaimana kita akan menguji?

Mari kita lancarkan contoh Tarantool dengan pengelogan tulis ke hadapan dilumpuhkan (wal_mode = tiada) dan penimbal rangkaian meningkat (baca di hadapan = 1 * 1024 * 1024). Pilihan pertama akan menghapuskan kerja dengan cakera, yang kedua akan memungkinkan untuk membaca lebih banyak permintaan daripada penimbal sistem pengendalian dan dengan itu meminimumkan bilangan panggilan sistem.

Untuk penanda aras yang berfungsi dengan data (sisipan, pemadaman, bacaan, dll.), sebelum memulakan penanda aras, ruang memtx akan (semula) dibuat, di mana nilai indeks utama dicipta oleh penjana nilai integer tertib ​(urutan).
Ruang DDL kelihatan seperti ini:

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

Jika perlu, sebelum menjalankan penanda aras, ruang diisi dengan 10,000 tupel borang

{id, "tuplΠ΅_<id>"}

Tuples diakses menggunakan nilai kunci rawak.

Penanda aras itu sendiri adalah permintaan tunggal kepada pelayan, yang dilaksanakan 10,000 kali (revolusi), yang seterusnya, dilaksanakan dalam lelaran. Lelaran diulang sehingga semua sisihan masa antara 5 lelaran berada dalam ralat 3%* yang boleh diterima. Selepas ini, keputusan purata diambil. Terdapat jeda 1 saat antara lelaran untuk mengelakkan pemproses daripada pendikit. Pengumpul sampah Lua dilumpuhkan sebelum setiap lelaran dan terpaksa dimulakan selepas ia selesai. Proses PHP dilancarkan hanya dengan sambungan yang diperlukan untuk penanda aras, dengan penimbalan output didayakan dan pengumpul sampah dilumpuhkan.

* Bilangan revolusi, lelaran dan ambang ralat boleh ditukar dalam tetapan penanda aras.

Persekitaran ujian

Keputusan yang diterbitkan di bawah telah dibuat pada MacBookPro (2015), sistem pengendalian - Fedora 30 (kernel versi 5.3.8-200.fc30.x86_64). Tarantool telah dilancarkan dalam docker dengan parameter "--network host".

Versi pakej:

Tarantool: 2.3.0-115-g5ba5ed37e
Docker: 19.03.3, bina a872fc2f86
PHP: 7.3.11 (cli) (dibina: 22 Okt 2019 08:11:04)
tarantool/pelanggan: 0.6.0
rybakit/msgpack: 0.6.1
ext-tarantool: 0.3.2 (+ tampalan untuk 7.3)*
ext-msgpack: 2.0.3
ext-async: 0.3.0-8c1da46
ext-swole: 4.4.12
ext-parallel: 1.1.3

* Malangnya, penyambung rasmi tidak berfungsi dengan versi PHP > 7.2. Untuk menyusun dan menjalankan sambungan pada PHP 7.3, saya terpaksa menggunakan tampalan.

Penemuan

Mod segerak

Protokol Tarantool menggunakan format binari Pek Mesej untuk menyusun mesej. Dalam penyambung PECL, bersiri disembunyikan jauh di dalam kedalaman perpustakaan dan mempengaruhi proses pengekodan daripada kod userland nampak tak mungkin. Penyambung PHP tulen, sebaliknya, menyediakan keupayaan untuk menyesuaikan proses pengekodan dengan melanjutkan pengekod standard atau dengan menggunakan pelaksanaan anda sendiri. Terdapat dua pengekod yang tersedia di luar kotak, satu adalah berdasarkan msgpack/msgpack-php (sambungan PECL MessagePack rasmi), yang satu lagi dihidupkan rybakit/msgpack (dalam PHP tulen).

Sebelum membandingkan penyambung, kami akan mengukur prestasi pengekod MessagePack untuk penyambung PHP dan dalam ujian lanjut kami akan menggunakan yang menunjukkan hasil terbaik:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Walaupun versi PHP (Tulen) adalah lebih rendah daripada sambungan PECL dalam kelajuan, dalam projek sebenar saya masih akan mengesyorkan menggunakannya rybakit/msgpack, kerana dalam sambungan MessagePack rasmi spesifikasi format hanya dilaksanakan sebahagiannya (contohnya, tiada sokongan untuk jenis data tersuai, tanpanya anda tidak akan dapat menggunakan Decimal - jenis data baharu yang diperkenalkan dalam Tarantool 2.3) dan mempunyai bilangan orang lain masalah (termasuk isu keserasian dengan PHP 7.4). Nah, secara umum, projek itu kelihatan terbengkalai.

Jadi, mari kita ukur prestasi penyambung dalam mod segerak:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Seperti yang dapat dilihat daripada graf, penyambung PECL (Tarantool) menunjukkan prestasi yang lebih baik berbanding dengan penyambung PHP (Pelanggan). Tetapi ini tidak menghairankan, memandangkan yang terakhir, selain dilaksanakan dalam bahasa yang lebih perlahan, sebenarnya melakukan lebih banyak kerja: objek baharu dibuat dengan setiap panggilan Meminta ΠΈ Tindak balas (dalam kes Pilih - juga Kriteria, dan dalam kes Kemas Kini/Upsert ― operasi), entiti berasingan Hubungan, Packer ΠΈ Handler mereka juga menambah overhed. Jelas sekali, fleksibiliti datang pada harga. Walau bagaimanapun, secara amnya, penterjemah PHP menunjukkan prestasi yang baik, walaupun terdapat perbezaan, ia tidak ketara dan, mungkin, akan menjadi lebih kurang apabila menggunakan pramuat dalam PHP 7.4, apatah lagi JIT dalam PHP 8.

Jom teruskan. Tarantool 2.0 memperkenalkan sokongan SQL. Mari cuba lakukan operasi Pilih, Sisip, Kemas kini dan Padam menggunakan protokol SQL dan bandingkan hasilnya dengan persamaan noSQL (binari):

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Keputusan SQL tidak begitu mengagumkan (biar saya ingatkan anda bahawa kami masih menguji mod segerak). Walau bagaimanapun, saya tidak akan kecewa tentang perkara ini lebih awal daripada masa; Sokongan SQL masih dalam pembangunan aktif (baru-baru ini, sebagai contoh, sokongan telah ditambah penyataan yang disediakan) dan, berdasarkan senarai isu-isu, enjin SQL akan menjalani beberapa pengoptimuman pada masa hadapan.

tak segerak

Nah, sekarang mari kita lihat cara sambungan Async boleh membantu kami meningkatkan hasil di atas. Untuk menulis atur cara tak segerak, sambungan menyediakan API berdasarkan coroutine, yang akan kami gunakan. Kami mendapati secara empirik bahawa bilangan coroutine yang optimum untuk persekitaran kita ialah 25:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
β€œSebarkan” 10,000 operasi merentasi 25 coroutine dan lihat apa yang berlaku:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Bilangan operasi sesaat meningkat lebih daripada 3 kali ganda untuk tarantool-php/client!

Malangnya, penyambung PECL tidak bermula dengan ext-async.

Bagaimana dengan SQL?

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Seperti yang anda lihat, dalam mod tak segerak perbezaan antara protokol binari dan SQL menjadi dalam margin ralat.

Swooole

Sekali lagi kami mengetahui bilangan coroutine yang optimum, kali ini untuk Swoole:
Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Mari berhenti pada 25. Mari ulangi helah yang sama seperti sambungan Async - edarkan 10,000 operasi antara 25 coroutine. Di samping itu, kami akan menambah satu lagi ujian di mana kami akan membahagikan semua kerja kepada 2 dua proses (iaitu, setiap proses akan melaksanakan 5,000 operasi dalam 25 coroutine). Proses akan dibuat menggunakan SwooleProcess.

Keputusan:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Swole menunjukkan hasil yang lebih rendah sedikit berbanding Async apabila dijalankan dalam satu proses, tetapi dengan 2 proses gambar berubah secara mendadak (nombor 2 tidak dipilih secara kebetulan; pada mesin saya, ia adalah 2 proses yang menunjukkan hasil terbaik).

Ngomong-ngomong, sambungan Async juga mempunyai API untuk bekerja dengan proses, tetapi di sana saya tidak melihat apa-apa perbezaan daripada menjalankan penanda aras dalam satu atau lebih proses (kemungkinan saya kacau di suatu tempat).

SQL vs protokol binari:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Seperti Async, perbezaan antara operasi binari dan SQL dihapuskan dalam mod tak segerak.

Selari

Memandangkan sambungan Selari bukan mengenai coroutine, tetapi mengenai benang, mari kita ukur bilangan optimum benang selari:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Ia sama dengan 16 pada mesin saya. Mari jalankan penanda aras penyambung pada 16 benang selari:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Seperti yang anda lihat, hasilnya lebih baik daripada sambungan tak segerak (tidak termasuk Swoole berjalan pada 2 proses). Ambil perhatian bahawa untuk penyambung PECL, operasi Kemas Kini dan Upsert kosong. Ini disebabkan oleh fakta bahawa operasi ini gagal dengan ralat - Saya tidak tahu sama ada ia adalah kesalahan ext-parallel, ext-tarantool, atau kedua-duanya.

Sekarang mari kita bandingkan prestasi SQL:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel
Perhatikan persamaan dengan graf untuk penyambung berjalan serentak?

bersama-sama

Dan akhirnya, mari kita ringkaskan semua keputusan dalam satu graf untuk melihat gambaran keseluruhan bagi sambungan yang diuji. Mari tambahkan hanya satu ujian baharu pada carta, yang belum kita lakukan - mari jalankan coroutine Async secara selari menggunakan Selari*. Idea untuk mengintegrasikan sambungan di atas sudah ada telah dibincangkan penulis, tetapi tiada kata sepakat dicapai, anda perlu melakukannya sendiri.

* Tidak mungkin untuk melancarkan coroutine Swoole dengan Parallel; nampaknya sambungan ini tidak serasi.

Jadi, keputusan akhir:

Mempercepatkan penyambung PHP untuk Tarantool menggunakan Async, Swoole dan Parallel

Daripada kesimpulan

Pada pendapat saya, hasilnya ternyata agak berbaloi, dan atas sebab tertentu saya yakin bahawa ini bukan had! Sama ada anda perlu memutuskan perkara ini dalam projek sebenar semata-mata untuk diri sendiri, saya hanya akan mengatakan bahawa bagi saya ia adalah percubaan yang menarik yang membolehkan anda menilai berapa banyak yang anda boleh "memerah" daripada penyambung TCP segerak dengan usaha yang minimum. Jika anda mempunyai idea untuk menambah baik penanda aras, saya berbesar hati untuk mempertimbangkan permintaan tarik anda. Semua kod dengan arahan pelancaran dan keputusan diterbitkan secara berasingan repositori.

Sumber: www.habr.com

Tambah komen