Jawaban:
Boost.Asio adalah pustaka C ++ yang dimulai dengan fokus pada jaringan, tetapi kemampuan I / O yang tidak sinkron telah diperluas ke sumber daya lainnya. Selain itu, dengan Boost.Asio menjadi bagian dari perpustakaan Boost, cakupannya sedikit dipersempit untuk mencegah duplikasi dengan perpustakaan Boost lainnya. Misalnya, Boost.Asio tidak akan memberikan abstraksi utas, karena Boost.Thread sudah menyediakannya.
Di sisi lain, libuv adalah library C dirancang untuk menjadi lapisan platform untuk Node.js . Ini memberikan abstraksi untuk IOCP pada Windows, kqueue pada macOS, dan epoll di Linux. Selain itu, sepertinya cakupannya sedikit meningkat untuk menyertakan abstraksi dan fungsionalitas, seperti utas, utas, dan komunikasi antar-utas.
Pada intinya, setiap perpustakaan menyediakan loop acara dan kemampuan I / O yang tidak sinkron. Mereka memiliki tumpang tindih untuk beberapa fitur dasar, seperti timer, soket, dan operasi asinkron. libuv memiliki cakupan yang lebih luas, dan menyediakan fungsionalitas tambahan, seperti abstraksi utas dan sinkronisasi, operasi sistem file sinkron dan asinkron, manajemen proses, dll. Sebaliknya, permukaan fokus jaringan asli Boost.Asio, karena menyediakan rangkaian jaringan yang lebih kaya terkait kemampuan, seperti ICMP, SSL, operasi pemblokiran sinkron dan non-pemblokiran, dan operasi tingkat yang lebih tinggi untuk tugas-tugas umum, termasuk membaca dari aliran hingga baris baru diterima.
Berikut ini adalah perbandingan singkat berdampingan pada beberapa fitur utama. Karena pengembang yang menggunakan Boost.Asio sering memiliki pustaka Boost lain yang tersedia, saya telah memilih untuk mempertimbangkan pustaka Boost tambahan jika pustaka tersebut disediakan secara langsung atau sepele untuk diterapkan.
libuv Boost Peristiwa Peristiwa: ya Asio Threadpool: yes Asio + Threads Threading: Utas: ya utas Sinkronisasi: yes Threads Operasi Sistem File: Sinkron: ya FileSystem Asinkron: ya Asio + Filesystem Pengatur waktu: ya Asio Scatter / Kumpulkan I / O [1] : no Asio Jaringan: ICMP: bukan Asio Resolusi DNS: ASYNC-only Asio SSL: tidak ada Asio TCP: ASync-only Asio UDP: ASYNC-only Asio Sinyal: Penanganan: ya Asio Mengirim: ya tidak IPC: Soket Domain UNIX: ya Asio Windows Named Pipe: yes Asio Manajemen proses: Melepaskan: ya Proses I / O Pipe: yes Process Pemijahan: Ya Proses Kueri Sistem: CPU: ya tidak Antarmuka Jaringan: ya tidak Serial Ports: tidak ya TTY: ya tidak Memuat Perpustakaan Bersama: yes Extension [2]
1. Menyebarkan / Mengumpulkan I / O .
2. Meningkatkan . Ekstensi tidak pernah diajukan untuk ditinjau ke Peningkatan. Sebagaimana dicatat di sini , penulis menganggapnya lengkap.
Sementara libuv dan Boost. Juga menyediakan loop acara, ada beberapa perbedaan halus antara keduanya:
uv_default_loop()
), daripada membuat loop baru ( uv_loop_new()
), karena komponen lain mungkin menjalankan loop default.io_service
adalah loop mereka sendiri yang memungkinkan untuk menjalankan beberapa utas. Untuk mendukung Peningkatan ini. Juga melakukan penguncian internal dengan mengorbankan beberapa kinerja . Revisi Boost.Asio ini sejarah menunjukkan bahwa sudah ada beberapa perbaikan kinerja untuk meminimalkan penguncian.uv_queue_work
. Ukuran threadpool dapat dikonfigurasi melalui variabel lingkungan UV_THREADPOOL_SIZE
. Pekerjaan akan dieksekusi di luar loop acara dan di dalam threadpool. Setelah pekerjaan selesai, penangan penyelesaian akan antri untuk berjalan dalam loop acara.io_service
dapat dengan mudah berfungsi sebagai satu sebagai akibat dari io_service
memungkinkan beberapa thread untuk menjalankan run
. Ini menempatkan tanggung jawab manajemen utas dan perilaku kepada pengguna, seperti yang dapat dilihat dalam contoh ini .EAGAIN
atau EWOULDBLOCK
.kill
dan penanganan sinyal dengan uv_signal_t
jenis dan uv_signal_*
operasinya.kill
, tetapi signal_set
memberikan penanganan sinyal.uv_pipe_t
jenis.local::stream_protocol::socket
atau local::datagram_protocol::socket
, dan windows::stream_handle
.Meskipun API berbeda berdasarkan bahasa saja, berikut adalah beberapa perbedaan utama:
Di dalam Boost.Asio, ada pemetaan satu-ke-satu antara operasi dan penangan. Misalnya, setiap async_write
operasi akan memanggil WriteHandler sekali. Ini berlaku untuk banyak operasi dan penangan libuv. Namun, libuv uv_async_send
mendukung pemetaan banyak-ke-satu. Beberapa uv_async_send
panggilan dapat menyebabkan uv_async_cb dipanggil satu kali.
Ketika berhadapan dengan tugas, seperti membaca dari aliran / UDP, menangani sinyal, atau menunggu timer, Boost. Rantai panggilan asinkron Sisio sedikit lebih eksplisit. Dengan libuv, pengamat diciptakan untuk menunjuk minat dalam acara tertentu. Lingkaran kemudian dimulai untuk pengamat, di mana panggilan balik disediakan. Setelah menerima acara yang menarik, callback akan dipanggil. Di sisi lain, Boost.Asio membutuhkan operasi yang akan dikeluarkan setiap kali aplikasi tertarik untuk menangani acara tersebut.
Untuk membantu mengilustrasikan perbedaan ini, berikut adalah loop baca asinkron dengan Boost.Asio, di mana async_receive
panggilan akan dikeluarkan beberapa kali:
void start()
{
socket.async_receive( buffer, handle_read ); ----.
} |
.----------------------------------------------'
| .---------------------------------------.
V V |
void handle_read( ... ) |
{ |
std::cout << "got data" << std::endl; |
socket.async_receive( buffer, handle_read ); --'
}
Dan di sini adalah contoh yang sama dengan libuv, di mana handle_read
dipanggil setiap kali pengamat mengamati bahwa soket memiliki data:
uv_read_start( socket, alloc_buffer, handle_read ); --.
|
.-------------------------------------------------'
|
V
void handle_read( ... )
{
fprintf( stdout, "got data\n" );
}
Sebagai hasil dari rantai panggilan asinkron di Boost.Asio dan pengamat di libuv, alokasi memori sering terjadi pada waktu yang berbeda. Dengan pengamat, libuv menolak alokasi sampai setelah menerima acara yang membutuhkan memori untuk ditangani. Alokasi dilakukan melalui panggilan balik pengguna, dipanggil internal ke libuv, dan menangguhkan tanggung jawab alokasi aplikasi. Di sisi lain, banyak operasi Boost.Asio mengharuskan memori dialokasikan sebelum mengeluarkan operasi asinkron, seperti kasus buffer
untuk async_read
. Boost.Asio memang menyediakan null_buffers
, yang dapat digunakan untuk mendengarkan suatu acara, memungkinkan aplikasi untuk menunda alokasi memori sampai memori diperlukan, meskipun ini sudah usang.
Perbedaan alokasi memori ini juga muncul dalam bind->listen->accept
loop. Dengan libuv, uv_listen
membuat loop acara yang akan memanggil panggilan balik pengguna ketika koneksi siap diterima. Ini memungkinkan aplikasi untuk menunda alokasi klien sampai suatu koneksi dicoba. Di sisi lain, Boost.Asio listen
hanya mengubah status acceptor
. The async_accept
mendengarkan untuk acara koneksi, dan membutuhkan rekan yang akan dialokasikan sebelum dipanggil.
Sayangnya, saya tidak memiliki nomor patokan konkret untuk membandingkan libuv dan Boost.Asio. Namun, saya telah mengamati kinerja yang sama menggunakan perpustakaan di aplikasi waktu nyata dan dekat waktu nyata. Jika angka keras diinginkan, uji patokan libuv dapat berfungsi sebagai titik awal.
Selain itu, sementara pembuatan profil harus dilakukan untuk mengidentifikasi hambatan yang sebenarnya, waspadai alokasi memori. Untuk libuv, strategi alokasi memori terutama terbatas pada callback pengalokasi. Di sisi lain, API Boost.Asio tidak memungkinkan untuk panggilan balik pengalokasi, dan sebaliknya mendorong strategi alokasi ke aplikasi. Namun, penangan / panggilan balik di Boost.Asio dapat disalin, dialokasikan, dan tidak dialokasikan. Boost.Asio memungkinkan aplikasi untuk menyediakan fungsi alokasi memori khusus untuk menerapkan strategi alokasi memori untuk penangan.
Perkembangan Asio dimulai setidaknya pada OCT-2004, dan diterima di Boost 1.35 pada 22-MAR-2006 setelah menjalani peer review selama 20 hari. Ini juga berfungsi sebagai implementasi referensi dan API untuk Proposal Perpustakaan Jaringan untuk TR2 . Boost.Asio memiliki cukup banyak dokumentasi , meskipun kegunaannya bervariasi dari pengguna ke pengguna.
API juga memiliki perasaan yang cukup konsisten. Selain itu, operasi asinkron secara eksplisit dalam nama operasi. Misalnya, accept
pemblokiran sinkron dan async_accept
asinkron. API menyediakan fungsi gratis untuk tugas I / O umum, misalnya, membaca dari aliran hingga \r\n
dibaca. Perhatian juga telah diberikan untuk menyembunyikan beberapa detail spesifik jaringan, seperti ip::address_v4::any()
mewakili alamat "semua antarmuka" dari 0.0.0.0
.
Akhirnya, Boost 1.47+ menyediakan pelacakan handler , yang dapat terbukti bermanfaat saat debugging, serta dukungan C ++ 11.
Berdasarkan grafik github mereka, pengembangan Node.js tanggal kembali ke setidaknya FEB-2009 , dan tanggal pengembangan libuv ke MAR-2011 . The uvbook adalah tempat yang bagus untuk pengenalan libuv. Dokumentasi API ada di sini .
Secara keseluruhan, API ini cukup konsisten dan mudah digunakan. Satu anomali yang mungkin menjadi sumber kebingungan adalah uv_tcp_listen
menciptakan loop pengamat. Hal ini berbeda dari pengamat lain yang umumnya memiliki uv_*_start
dan uv_*_stop
sepasang fungsi untuk mengontrol kehidupan loop pengamat. Juga, beberapa uv_fs_*
operasi memiliki jumlah argumen yang layak (hingga 7). Dengan perilaku sinkron dan asinkron ditentukan pada adanya panggilan balik (argumen terakhir), visibilitas perilaku sinkron dapat dikurangi.
Akhirnya, sekilas sekilas pada libuv commit history menunjukkan bahwa pengembangnya sangat aktif.
uv_async_send
panggilan, dan menangani semuanya dengan satu panggilan balik. Itu didokumentasikan di sini . Juga, terima kasih semuanya.
Baik. Saya memiliki beberapa pengalaman dalam menggunakan kedua perpustakaan dan dapat mengklarifikasi beberapa hal.
Pertama, dari sudut pandang konseptual perpustakaan ini sangat berbeda dalam desain. Mereka memiliki arsitektur yang berbeda, karena berskala berbeda. Boost.Asio adalah perpustakaan jaringan besar yang ditujukan untuk digunakan dengan protokol TCP / UDP / ICMP, POSIX, SSL dan sebagainya. Libuv hanyalah lapisan untuk abstraksi lintas-platform IOCP untuk Node.js, terutama. Jadi libuv secara fungsional merupakan subset dari Boost.Asio (fitur umum hanya thread Sockets TCP / UDP, timer). Karena itu, kami dapat membandingkan perpustakaan ini hanya dengan beberapa kriteria:
Integrasi dengan fitur C ++ baru: Asio lebih baik (Asio 1,51 secara ekstensif menggunakan model asinkron C ++ 11, memindahkan semantik, templat variadik). Terkait dengan kematangan, Asio adalah proyek yang lebih stabil dan matang dengan dokumentasi yang baik (jika dibandingkan dengan libuv deskripsi header), banyak informasi di Internet (ceramah video, blog: http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg = 1 , dll.) Dan bahkan buku (bukan untuk profesional tetapi: http://en.highscore.de/cpp/boost/index.html ). Libuv hanya memiliki satu buku online (tetapi juga bagus) http://nikhilm.github.com/uvbook/index.htmldan beberapa pembicaraan video, sehingga akan sulit untuk mengetahui semua rahasia (perpustakaan ini memiliki banyak rahasia). Untuk diskusi fungsi yang lebih spesifik lihat komentar saya di bawah ini.
Sebagai kesimpulan, saya harus mengatakan bahwa itu semua tergantung pada tujuan Anda, proyek Anda dan apa yang ingin Anda lakukan secara konkret.
Satu perbedaan besar adalah penulis Asio (Christopher Kohlhoff) sedang merawat perpustakaannya untuk dimasukkan dalam C ++ Standard Library, lihat http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2175 .pdf dan http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4370.html
Menambahkan status portabilitas: Saat memposting jawaban ini dan sesuai dengan upaya saya sendiri: