Libxev adalah loop acara lintas platform. LibXev menyediakan abstraksi loop acara terpadu untuk IO, timer, sinyal, acara, dan banyak lagi yang berfungsi pada macOS, Windows, Linux, dan WebAssembly (browser dan Wasi). Ini ditulis dalam zig tetapi mengekspor API yang kompatibel C (yang selanjutnya membuatnya kompatibel dengan bahasa apa pun di luar sana yang dapat berkomunikasi dengan API C).
Status Proyek :? Kualitas alfa-ish yang tidak stabil. Daftar fitur ini cukup bagus di berbagai platform, tetapi ada banyak fitur yang hilang. Proyek ini belum diuji dengan baik di lingkungan dunia nyata dan ada banyak buah yang menggantung rendah untuk optimasi kinerja. Saya juga tidak menjanjikan kompatibilitas API pada saat ini. Jika Anda ingin produksi produksi siap, berkualitas tinggi, implementasi loop umum, lihat Libuv, Libev, dll.
Mengapa Perpustakaan Loop Acara Baru? Beberapa alasan. Satu, saya pikir Zig tidak memiliki loop acara umum yang sebanding dengan libuv dalam fitur ("umum" menjadi kata kunci di sini). Dua, saya ingin membangun perpustakaan seperti ini di sekitar pola desain io_uring, bahkan meniru gayanya di atas primitif OS lainnya (kredit untuk posting blog yang luar biasa ini). Tiga, saya ingin perpustakaan loop acara yang dapat dibangun untuk WebAssembly (baik Wasi dan berdiri bebas) dan itu tidak benar -benar cocok dengan tujuan gaya API perpustakaan yang ada tanpa membawa sesuatu yang sangat berat seperti Emscripten. Motivasi untuk perpustakaan ini terutama adalah menggaruk gatal saya sendiri!
Cross-Platform. Linux ( io_uring dan epoll ), macOS ( kqueue ), WebAssembly + wasi ( poll_oneoff , runtimes berulir dan non-threaded). (Dukungan Windows direncanakan dan segera hadir)
Proactor API. Pekerjaan diserahkan ke LibXev Event Loop dan penelepon diberitahu tentang penyelesaian pekerjaan, sebagai lawan dari kesiapan kerja.
Alokasi runtime nol. Ini membantu membuat kinerja runtime lebih mudah diprediksi dan membuat LibXev cocok untuk lingkungan tertanam.
Pengatur waktu, TCP, UDP, file, proses. API platform-agnostik tingkat tinggi untuk berinteraksi dengan timer, soket TCP/UDP, file, proses, dan banyak lagi. Untuk platform yang tidak mendukung Async IO, operasi file secara otomatis dijadwalkan ke kumpulan utas.
Kumpulan benang generik (opsional). Anda dapat membuat kumpulan utas generik, mengkonfigurasi pemanfaatan sumber daya, dan menggunakannya untuk melakukan tugas latar belakang khusus. Kumpulan utas digunakan oleh beberapa backend untuk melakukan tugas-tugas yang tidak memblokir yang tidak memiliki API non-blocking yang andal (seperti operasi file lokal dengan kqueue ). Kumpulan utas dapat dibagikan di beberapa utas dan loop acara untuk mengoptimalkan pemanfaatan sumber daya.
API tingkat rendah dan tingkat tinggi. API tingkat tinggi adalah platform-agnostik tetapi memiliki beberapa perilaku yang memiliki pendapat dan fleksibilitas terbatas. API tingkat tinggi direkomendasikan tetapi API tingkat rendah selalu merupakan penetasan pelarian yang tersedia. API tingkat rendah khusus platform dan menyediakan mekanisme bagi pengguna LibXev untuk memeras kinerja maksimum. API tingkat rendah hanya cukup abstraksi di atas antarmuka OS untuk membuatnya lebih mudah digunakan tanpa mengorbankan kinerja yang terlihat.
Pengocok pohon (zig). Ini adalah fitur zig, tetapi secara substansial menguntungkan perpustakaan seperti libxev. Zig hanya akan menyertakan panggilan fungsi dan fitur yang sebenarnya Anda gunakan. Jika Anda tidak menggunakan jenis pengamat tingkat tinggi tertentu (seperti soket UDP), maka fungsionalitas yang terkait dengan abstraksi itu tidak dikompilasi ke dalam biner akhir Anda sama sekali. Ini memungkinkan libxev mendukung fungsionalitas "bagus-untuk-memiliki" opsional yang dapat dianggap "kembung" dalam beberapa kasus, tetapi pengguna akhir tidak harus membayarnya.
Bebas ketergantungan. Libxev tidak memiliki ketergantungan selain API OS bawaan saat runtime. Perpustakaan C tergantung pada libc. Ini membuatnya sangat mudah untuk kompilasi silang.
Ada banyak fitur yang hilang yang masih ingin saya tambahkan:
Dan lebih banyak ...
Ada banyak ruang untuk peningkatan kinerja, dan saya ingin sepenuhnya jelas bahwa saya belum melakukan banyak pekerjaan optimisasi. Tetap saja, kinerja terlihat bagus. Saya sudah mencoba untuk port banyak tolok ukur libuv untuk menggunakan libxev API.
Saya tidak akan memposting hasil benchmark tertentu sampai saya memiliki lingkungan yang lebih baik untuk menjalankannya. Sebagai generalisasi yang sangat luas , Anda tidak boleh melihat perlambatan menggunakan libxev dibandingkan dengan loop peristiwa besar lainnya. Ini mungkin berbeda berdasarkan fitur per fitur, dan jika Anda dapat menunjukkan kinerja yang sangat buruk dalam masalah, saya tertarik untuk menyelesaikannya!
Contoh di bawah ini menunjukkan program identik yang ditulis dalam zig dan di C yang menggunakan libxev untuk menjalankan timer 5S tunggal. Ini hampir konyol betapa sederhananya tetapi dimaksudkan untuk hanya menyampaikan nuansa keseluruhan perpustakaan daripada kasus penggunaan praktis.
| Zig | C |
const xev = @import ( "xev" );
pub fn main () ! void {
var loop = try xev . Loop . init (.{});
defer loop . deinit ();
const w = try xev . Timer . init ();
defer w . deinit ();
// 5s timer
var c : xev.Completion = undefined ;
w . run ( & loop , & c , 5000 , void , null , & timerCallback );
try loop . run ( .until_done );
}
fn timerCallback (
userdata : ? * void ,
loop : * xev.Loop ,
c : * xev.Completion ,
result : xev . Timer . RunError ! void ,
) xev.CallbackAction {
_ = userdata ;
_ = loop ;
_ = c ;
_ = result catch unreachable ;
return .disarm ;
} | # include < stddef . h >
# include < stdio . h >
# include < xev . h >
xev_cb_action timerCallback ( xev_loop * loop , xev_completion * c , int result , void * userdata ) {
return XEV_DISARM ;
}
int main ( void ) {
xev_loop loop ;
if ( xev_loop_init ( & loop ) != 0 ) {
printf ( "xev_loop_init failure n " );
return 1 ;
}
xev_watcher w ;
if ( xev_timer_init ( & w ) != 0 ) {
printf ( "xev_timer_init failure n " );
return 1 ;
}
xev_completion c ;
xev_timer_run ( & w , & loop , & c , 5000 , NULL , & timerCallback );
xev_loop_run ( & loop , XEV_RUN_UNTIL_DONE );
xev_timer_deinit ( & w );
xev_loop_deinit ( & loop );
return 0 ;
} |
Instruksi ini hanya untuk pengguna hilir zig. Jika Anda menggunakan C API ke LibXev, lihat bagian "Bangun".
Paket ini bekerja dengan manajer paket zig yang diperkenalkan di zig 0.11. Buat file build.zig.zon seperti ini:
.{
. name = "my-project" ,
. version = "0.0.0" ,
. dependencies = .{
. libxev = .{
. url = "https://github.com/mitchellh/libxev/archive/<git-ref-here>.tar.gz" ,
. hash = "12208070233b17de6be05e32af096a6760682b48598323234824def41789e993432c" ,
},
},
} Dan di build.zig Anda. Zig:
const xev = b . dependency ( "libxev" , .{ . target = target , . optimize = optimize });
exe . addModule ( "xev" , xev . module ( "xev" ));? Dokumentasi adalah pekerjaan dalam proses. ?
Saat ini, dokumentasi tersedia dalam tiga formulir: halaman pria , contoh , dan komentar kode. Di masa depan, saya berencana menulis panduan terperinci dan dokumentasi API dalam bentuk situs web, tetapi saat ini tidak tersedia.
Halaman pria relatif detail! xev(7) akan memberi Anda gambaran yang baik dari seluruh perpustakaan. xev-zig(7) dan xev-c(7) masing-masing akan memberikan ikhtisar Zig dan C API. Dari sana, halaman pria specifc API seperti xev_loop_init(3) tersedia. Ini adalah dokumentasi terbaik saat ini.
Ada banyak cara untuk menelusuri halaman pria. Yang paling ramah adalah hanya menelusuri sumber halaman RAW Man di docs/ Directory di browser web Anda. Sumber halaman pria adalah sintaksis seperti penurunan harga sehingga membuatnya baik-baik saja di browser Anda melalui GitHub.
Pendekatan lain adalah menjalankan zig build -Dman-pages dan halaman pria akan tersedia di zig-out . Ini membutuhkan SCDOC untuk diinstal (ini tersedia di sebagian besar manajer paket). Setelah Anda membangun halaman pria, Anda dapat membuatnya dengan jalan:
$ man zig-out/share/man/man7/xev.7
Dan pendekatan terakhir adalah menginstal libxev melalui manajer paket favorit Anda (jika dan bila tersedia), yang semoga harus memasukkan halaman pria Anda ke jalur pria Anda, sehingga Anda bisa melakukan man 7 xev .
Ada contoh yang tersedia dalam examples/ folder. Contohnya tersedia di kedua C dan Zig, dan Anda dapat mengetahui mana yang menggunakan ekstensi file.
Untuk membangun contoh, gunakan yang berikut:
$ zig build -Dexample-name=_basic.zig
...
$ zig-out/bin/example-basic
...
Nilai -Dexample-name harus menjadi nama file termasuk ekstensi.
Kode Zig dikomentari dengan baik. Jika Anda nyaman membaca komentar kode, Anda dapat menemukan banyak wawasan di dalamnya. Sumbernya ada di direktori src/ .
Build membutuhkan pemasangan zig malam terbaru. Libxev tidak memiliki dependensi bangunan lain.
Setelah diinstal, zig build install sendiri akan membangun perpustakaan lengkap dan mengeluarkan direktori yang kompatibel dengan FHS di zig-out . Anda dapat menyesuaikan direktori output dengan flag --prefix .
Libxev memiliki suite tes yang besar dan berkembang. Untuk menjalankan tes untuk platform saat ini:
$ zig build test
...Ini akan menjalankan semua tes untuk semua fitur yang didukung untuk platform host saat ini. Misalnya, di Linux ini akan menjalankan rangkaian tes IO_uring dan Epoll penuh.
Anda dapat membangun dan menjalankan tes untuk platform lain dengan mengkompilasi silang uji dapat dieksekusi, menyalinnya ke mesin target dan mengeksekusi. Misalnya, di bawah ini menunjukkan cara bersaing silang dan membangun tes untuk macOS dari Linux:
$ zig build -Dtarget=aarch64-macos -Dinstall-tests
...
$ file zig-out/bin/xev-test
zig-out/bin/xev-test: Mach-O 64-bit arm64 executableWasi adalah kasus khusus. Anda dapat menjalankan tes untuk WASI jika Anda sudah menginstal Wasmtime:
$ zig build test -Dtarget=wasm32-wasi -Dwasmtime
...