Bagaimana libuv dibandingkan dengan Boost / ASIO?

239

Saya akan tertarik pada aspek-aspek seperti:

  • ruang lingkup / fitur
  • kinerja
  • kematangan
oberstet
sumber
20
Mari kita kembali pertanyaan ini dan dapatkan jawaban yang bagus!
Viet
\ o / .. semoga kita mendapatkan jawaban yang berwawasan luas!
oberstet

Jawaban:

493

Cakupan

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.


Daftar Fitur

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.

Loop Acara

Sementara libuv dan Boost. Juga menyediakan loop acara, ada beberapa perbedaan halus antara keduanya:

  • Sementara libuv mendukung banyak loop peristiwa, ia tidak mendukung menjalankan loop yang sama dari beberapa utas. Karena alasan ini, kehati-hatian harus diambil ketika menggunakan loop default ( uv_default_loop()), daripada membuat loop baru ( uv_loop_new()), karena komponen lain mungkin menjalankan loop default.
  • Boost.Asio tidak memiliki gagasan tentang loop default; semua io_serviceadalah 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.

Threadpool

  • libuv's menyediakan threadpool melalui 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.
  • Sementara Boost.Asio tidak menyediakan threadpool, io_servicedapat dengan mudah berfungsi sebagai satu sebagai akibat dari io_servicememungkinkan beberapa thread untuk menjalankan run. Ini menempatkan tanggung jawab manajemen utas dan perilaku kepada pengguna, seperti yang dapat dilihat dalam contoh ini .

Threading dan Sinkronisasi

  • libuv menyediakan abstraksi untuk utas dan tipe sinkronisasi.
  • Boost.Thread menyediakan utas dan tipe sinkronisasi. Banyak dari tipe ini mengikuti standar C ++ 11, tetapi juga menyediakan beberapa ekstensi. Sebagai hasil dari Boost.Asio memungkinkan beberapa utas untuk menjalankan satu loop peristiwa, ia menyediakan untaian sebagai sarana untuk membuat permintaan berurutan dari penangan event tanpa menggunakan mekanisme penguncian eksplisit.

Operasi Sistem File

  • libuv menyediakan abstraksi untuk banyak operasi sistem file. Ada satu fungsi per operasi, dan setiap operasi dapat berupa pemblokiran sinkron atau asinkron. Jika panggilan balik disediakan, maka operasi akan dijalankan secara tidak serempak di dalam threadpool internal. Jika panggilan balik tidak disediakan, maka panggilan tersebut akan diblokir secara sinkron.
  • Boost.Filesystem menyediakan panggilan pemblokiran sinkron untuk banyak operasi sistem file. Ini dapat dikombinasikan dengan Boost.Asio dan threadpool untuk membuat operasi sistem file asinkron.

Jaringan

  • libuv mendukung operasi asinkron pada soket UDP dan TCP, serta resolusi DNS. Pengembang aplikasi harus menyadari bahwa deskriptor file yang mendasarinya diatur ke non-pemblokiran. Oleh karena itu, operasi sinkron asli harus memeriksa nilai balik dan kesalahan untuk EAGAINatau EWOULDBLOCK.
  • Boost.Asio sedikit lebih kaya dalam dukungan jaringannya. Selain itu, banyak fitur yang disediakan oleh jaringan libuv, Boost.Asio mendukung soket SSL dan ICMP. Selain itu, Boost.Asio menyediakan operasi pemblokiran sinkron dan non-pemblokiran sinkron, sebagai tambahan untuk operasi asinkronnya. Ada banyak fungsi berdiri bebas yang menyediakan operasi tingkat tinggi umum, seperti membaca jumlah byte yang ditetapkan, atau sampai karakter pembatas yang ditentukan dibaca.

Sinyal

  • libuv menyediakan abstraksi killdan penanganan sinyal dengan uv_signal_tjenis dan uv_signal_*operasinya.
  • Boost.Asio tidak memberikan abstraksi kill, tetapi signal_setmemberikan penanganan sinyal.

IPC


Perbedaan API

Meskipun API berbeda berdasarkan bahasa saja, berikut adalah beberapa perbedaan utama:

Asosiasi Operasi dan Penangan

Di dalam Boost.Asio, ada pemetaan satu-ke-satu antara operasi dan penangan. Misalnya, setiap async_writeoperasi akan memanggil WriteHandler sekali. Ini berlaku untuk banyak operasi dan penangan libuv. Namun, libuv uv_async_sendmendukung pemetaan banyak-ke-satu. Beberapa uv_async_sendpanggilan dapat menyebabkan uv_async_cb dipanggil satu kali.

Panggil Chains vs. Watcher Loops

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_receivepanggilan 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_readdipanggil 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" );
}

Alokasi memori

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 bufferuntuk 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->acceptloop. Dengan libuv, uv_listenmembuat 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 listenhanya mengubah status acceptor. The async_acceptmendengarkan untuk acara koneksi, dan membutuhkan rekan yang akan dialokasikan sebelum dipanggil.


Performa

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.


Kematangan

Tingkatkan Asio

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, acceptpemblokiran sinkron dan async_acceptasinkron. API menyediakan fungsi gratis untuk tugas I / O umum, misalnya, membaca dari aliran hingga \r\ndibaca. 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.

libuv

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_listenmenciptakan loop pengamat. Hal ini berbeda dari pengamat lain yang umumnya memiliki uv_*_startdan uv_*_stopsepasang 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.

Tanner Sansbury
sumber
2
Terima kasih sobat! Jawaban bagus! Saya tidak bisa memikirkan sesuatu yang lebih komprehensif :)
Viet
1
Sangat senang dengan jawabannya, saya menghadiahkan Anda dengan hadiah :) Biarkan SO untuk memutuskan jawaban terbaik untuk dirinya sendiri.
Viet
28
Jawaban yang luar biasa. Ini mencakup baik gambar tingkat tinggi, maupun spesifik, perbedaan penting dalam detail (seperti yaitu threading / eventloop). Terima kasih banyak!
oberstet
1
@oberstet: Tidak. Saya telah memperbarui jawaban untuk menyebutkan bahwa sebagian besar operasi libuv adalah satu-ke-satu. Namun, libuv dapat mengakumulasikan banyak uv_async_sendpanggilan, dan menangani semuanya dengan satu panggilan balik. Itu didokumentasikan di sini . Juga, terima kasih semuanya.
Tanner Sansbury
2
Penguncian internal pada loop acara di Boost.Asio terlihat menakutkan dari sudut pandang kinerja. Bagaimana bisa memiliki kinerja yang mirip dengan libuv bebas kunci? Mungkin menambahkan pernyataan peringatan di bagian kinerja dapat membantu.
zeodtr
46

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:

  1. Integrasi dengan Node.js - Libuv jauh lebih baik karena ditujukan untuk ini (kita dapat sepenuhnya mengintegrasikannya dan menggunakannya dalam semua aspek, misalnya cloud misalnya windows azure). Tetapi Asio juga mengimplementasikan fungsi yang hampir sama dengan lingkungan yang didorong oleh antrian event Node.js.
  2. Kinerja IOCP - Saya tidak bisa melihat perbedaan besar, karena kedua pustaka ini abstrak yang mendasari OS API. Tetapi mereka melakukannya dengan cara yang berbeda: Asio banyak menggunakan fitur C ++ seperti templat dan terkadang TMP. Libuv adalah pustaka C asli. Namun demikian, realisasi IOCP Asio sangat efisien. Soket UDP di Asio tidak cukup baik, lebih baik menggunakan libuv untuk mereka.

    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.

Oleksandr Karaberov
sumber
11
Yang penting adalah keterampilan dan pengalaman teknis Anda. Salam ramah dari seorang Kuba.
dsign
2
Saya setuju dengan semua poin Anda kecuali dokumentasi Asio. Dokumentasi resmi tidak memberikan keadilan bagi perpustakaan yang luar biasa ini. Ada banyak dokumen lain dan tambahan percakapan dari penulis yang saya temukan sangat berguna. Dan saya belum menemukan buku untuk Asio. Bisakah Anda menautkan itu dalam jawaban Anda? Ini akan sangat membantu.
Vikas
@vikas Ya saya setuju bahwa dokumentasi buruk dan kadang-kadang bertentangan tetapi dibandingkan dengan libuv itu bagus untuk memulai. Adapun buku saya mengedit jawaban saya tapi saya pikir Anda telah melihatnya sebelumnya (sayangnya tidak ada buku yang sepenuhnya didedikasikan untuk Meningkatkan - hanya tersebar informasi)
Oleksandr Karaberov
Apa yang Anda maksud dengan "Jadi libuv secara fungsional merupakan bagian dari Boost.Asio (TCP / UDP / Soket dan utas)"? Menurut TOC, nikhilm.github.com/uvbook/index.html libuv memiliki aplikasi yang lebih luas kemudian meningkatkan :: asio.
Sergei Nikulov
7
@AlexanderKaraberov dapatkah Anda memperluas masalah ASIO dengan UDP?
Bruno Martinez
2

Menambahkan status portabilitas: Saat memposting jawaban ini dan sesuai dengan upaya saya sendiri:

  • Boost.ASIO tidak memiliki dukungan resmi untuk iOS dan Android, mis. Sistem build-nya tidak berfungsi untuk iOS.
  • libuv dibuat dengan mudah untuk iOS dan Android, dengan dukungan resmi untuk Android tepat di dokumen mereka . Skrip build iOS generik saya sendiri untuk proyek berbasis Autotools bekerja tanpa masalah.
kakyo
sumber
Sangat mudah untuk membangun kerangka kerja lintas platform untuk iOS dan andriod menggunakan bazel menggunakan aturan bazel boost build.
nnrales