Libuv Boost / ASIO ile nasıl karşılaştırılır?


239

Şunun gibi konularla ilgileniyorum:

  • kapsam / özellikler
  • verim
  • olgunluk

20
Bu soruyu geri alalım ve iyi cevaplar alalım!
Viet

\ o / .. umarım bazı içgörülü cevaplar alırız!
oberstet

Yanıtlar:


493

Dürbün

Boost.Asio , ağ üzerinde odaklanarak başlayan bir C ++ kütüphanesidir, ancak eşzamansız I / O özellikleri diğer kaynaklara genişletilmiştir. Ayrıca, Boost.Asio, Boost kitaplıklarının bir parçası olduğundan, diğer Boost kitaplıklarıyla çoğaltmayı önlemek için kapsamı biraz daraltılır. Örneğin, Boost.Asio , Boost.Thread zaten bir iş parçacığı soyutlaması sağlamaz .

Öte yandan libuv , Node.js için platform katmanı olarak tasarlanmış bir C kütüphanesidir . Bu bir Özet sağlar IOCP Windows üzerinde, kqueue MacOS üzerinde ve epoll Linux üzerinde. Ek olarak, kapsamı, iş parçacıkları, iş parçacıkları havuzları ve iş parçacıkları arası iletişim gibi soyutlamaları ve işlevleri içerecek şekilde biraz artmış gibi görünüyor.

Özünde, her kütüphane bir olay döngüsü ve asenkron I / O özellikleri sağlar. Zamanlayıcılar, soketler ve eşzamansız işlemler gibi bazı temel özellikler için örtüşürler. libuv daha geniş bir kapsama sahiptir ve iş parçacığı ve senkronizasyon soyutlamaları, senkron ve asenkron dosya sistemi işlemleri, süreç yönetimi, vb. gibi ek işlevler sağlar. ICMP, SSL, eşzamanlı engelleme ve engellemesiz işlemler gibi özellikler ve bir satırsonu alınana kadar akıştan okuma da dahil olmak üzere yaygın görevler için daha üst düzey işlemler.


Özellik listesi

İşte bazı önemli özelliklerin kısa yan yana karşılaştırması. Boost.Asio kullanan geliştiriciler genellikle başka Boost kütüphaneleri bulunduğundan, doğrudan sağlandıysa veya uygulanması önemsizse ek Boost kütüphanelerini düşünmeyi seçtim.

                         libuv Boost
Etkinlik Döngüsü: evet Asio
Threadpool: evet Asio + Konular
Diş:              
  Konular: evet Konular
  Senkronizasyon: evet Konular
Dosya Sistemi İşlemleri:
  Senkronize: evet FileSystem
  Asenkron: evet Asio + Dosya Sistemi
Zamanlayıcılar: evet Asio
Dağılım / Toplama G / Ç [1] : Asio yok
ağ:
  ICMP: hayır Asio
  DNS Çözünürlüğü: only async asio
  SSL: hayır Asio
  TCP: yalnızca asenkron Asio
  UDP: yalnızca asenkron Asio
Sinyal:
  Kullanım: evet Asio
  Gönderme: evet hayır
IPC:
  UNIX Alan Adı Yuvaları: evet Asio
  Windows Adlandırılmış Boru: evet Asio
Süreç yönetimi:
  Ayırma: evet Süreci
  G / Ç Borusu: evet Süreci
  Yumurtlama: evet Süreci
Sistem Sorguları:
  CPU: evet hayır
  Ağ Arayüzü: evet hayır
Seri Portlar: hayır evet
TTY: evet hayır
Paylaşılan Kitaplık Yükleme: evet Eklenti [2]

1. Saçılma / Toplama G / Ç .

2. Boost.Eextension asla Boost'a incelenmek üzere gönderilmedi. Belirtildiği gibi burada , yazar bunun tam olarak kabul eder.

Olay Döngüsü

Hem libuv hem de Boost.Asio olay döngüleri sağlarken, ikisi arasında bazı ince farklar vardır:

  • Libuv birden çok olay döngüsünü desteklese de, aynı döngüyü birden çok iş parçacığından çalıştırmayı desteklemez. Bu nedenle, başka bir bileşen varsayılan döngüyü çalıştırıyor olabileceğinden, uv_default_loop()yeni bir döngü ( uv_loop_new()) oluşturmak yerine varsayılan döngü ( ) kullanılırken dikkatli olunmalıdır .
  • Boost.Asio varsayılan bir döngü kavramına sahip değildir; hepsi io_servicebirden çok iş parçacığının çalışmasına izin veren kendi döngüleridir. Bu Boost'u desteklemek için Asio , bazı performans pahasına dahili kilitleme gerçekleştirir . Asio'nun düzeltme geçmişi , kilidi en aza indirmek için çeşitli performans iyileştirmeleri olduğunu gösterir.

threadpool

  • libuv's aracılığıyla bir threadpool sağlar uv_queue_work. İş parçacığı boyutu ortam değişkeni üzerinden yapılandırılabilir UV_THREADPOOL_SIZE. İş, olay döngüsü dışında ve iş parçacığı içinde yürütülür. İş tamamlandığında, tamamlama işleyicisi olay döngüsü içinde çalışmak üzere sıraya alınır.
  • Boost.Asio bir iş parçacığı havuzu sağlamazken, birden çok iş parçacığının çağrılmasına izin vermenin io_servicebir sonucu olarak kolayca işlev görebilir . Bu, bu örnekte görülebileceği gibi, kullanıcıya iplik yönetimi ve davranış sorumluluğunu koyar .io_servicerun

Diş Açma ve Senkronizasyon

  • libuv iş parçacığı ve senkronizasyon türleri için bir soyutlama sağlar.
  • Boost.Thread bir iş parçacığı ve senkronizasyon türleri sağlar. Bu türlerin çoğu C ++ 11 standardını yakından takip eder, ancak bazı uzantılar da sağlar. Boost.Asio'nun birden çok iş parçacığının tek bir olay döngüsünü çalıştırmasına izin vermesinin bir sonucu olarak, açık kilitleme mekanizmaları kullanmadan olay işleyicilerinin sıralı bir şekilde çağrılmasını sağlamanın bir yolu olarak teller sağlar .

Dosya Sistemi İşlemleri

  • libuv birçok dosya sistemi işlemine bir soyutlama sağlar. Her işlem için bir işlev vardır ve her işlem eşzamanlı engelleme veya eşzamansız olabilir. Bir geri arama sağlanırsa, işlem dahili bir iş parçacığı içinde eşzamansız olarak yürütülür. Bir geri arama sağlanmazsa, çağrı eşzamanlı engelleme olur.
  • Boost.Filesystem birçok dosya sistemi işlemi için senkronize engelleme çağrıları sağlar. Bunlar, zaman uyumsuz dosya sistemi işlemleri oluşturmak için Boost.Asio ve bir threadpool ile birleştirilebilir.

  • libuv, UDP ve TCP soketlerinde eşzamansız işlemleri ve DNS çözümlemesini destekler. Uygulama geliştiricileri, temeldeki dosya tanımlayıcılarının engellenmeyecek şekilde ayarlandığını bilmelidir. Bu nedenle, yerel eşzamanlı işlemler dönüş değerlerini ve errno öğesiniEAGAIN veya için kontrol etmelidir EWOULDBLOCK.
  • Boost.Asio, ağ desteği açısından biraz daha zengindir. Ek olarak libuv ağının sağladığı birçok özellik, SSL ve ICMP soketlerini destekleyen Boost.Asio. Ayrıca Boost.Asio, eşzamansız işlemlerine ek olarak eşzamanlı engelleme ve eşzamanlı engelleme olmayan işlemler de sağlar. Belirli bir bayt miktarını okumak veya belirli bir sınırlayıcı karakter okunana kadar ortak üst düzey işlemler sağlayan çok sayıda serbest duran işlev vardır.

işaret

  • libuv, türü ve işlemleri killile bir soyutlama ve sinyal işleme sağlar.uv_signal_tuv_signal_*
  • Boost.Asio bir soyutlamayı kanıtlamaz kill, ancak signal_setsinyal işleme sağlar.

IPC


API Farkları

API'lar yalnızca dile göre farklı olsa da, burada birkaç önemli fark vardır:

Operasyon ve İşleyici Derneği

Boost.Asio içinde, bir işlem ile bir işleyici arasında bire bir eşleme vardır. Örneğin, her async_writeişlem bir kez WriteHandler'ı çağırır . Bu, birçok libuv işlemi ve işleyicisi için geçerlidir. Bununla birlikte, libuv'lar çoktan uv_async_sendbire eşlemeyi destekler. Birden fazla uv_async_sendçağrı uv_async_cb'nin bir kez çağrılmasına neden olabilir .

Çağrı Zincirleri ve Gözcü Döngüleri

Bir akış / UDP'den okuma, sinyalleri işleme veya zamanlayıcıları bekleme gibi görevlerle uğraşırken Boost.Asio'nun asenkron çağrı zincirleri biraz daha açıktır. Libuv ile belirli bir etkinliğe ilgi göstermek için bir gözlemci oluşturulur. Daha sonra izleyici için bir geri çağrı sağlanan bir döngü başlatılır. Çıkar olayı alındıktan sonra geri arama başlatılacaktır. Öte yandan, Boost.Asio, uygulamanın olayı işlemekle her ilgilenişinde bir işlem yapılmasını gerektirir.

Bu farkı göstermeye yardımcı olmak için, Boost.Asio ile async_receiveçağrının birden çok kez verileceği eşzamansız bir okuma döngüsü :

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

Ve burada, handle_readgözlemcinin soketin veri içerdiğini her gözlemlediğinde çağrılan libuv ile aynı örnek :

uv_read_start( socket, alloc_buffer, handle_read ); --.
                                                      |
    .-------------------------------------------------'
    |
    V
void handle_read( ... )
{
  fprintf( stdout, "got data\n" );
}

Bellek Ayırma

Boost.Asio'daki asenkron çağrı zincirlerinin ve libuv'daki gözlemcilerin bir sonucu olarak, bellek ayırma genellikle farklı zamanlarda gerçekleşir. Gözlemcilerde libuv, tahsisi hafızanın işlenmesini gerektiren bir olay alana kadar savunur. Tahsis, bir kullanıcı geri çağrısı yoluyla yapılır, libuv için dahili olarak çağrılır ve uygulamanın dağıtma sorumluluğunu ortadan kaldırır. Öte yandan, Boost.Asio operasyonların birçok bellek Böyle durumunda olduğu gibi, uyumsuz işlemi vermeden önce tahsis gerektirir bufferiçin async_read. Boost.Asio, null_buffersbir olayı dinlemek için kullanılabilecek şekilde sağlayarak uygulamaların bellek gerekene kadar bellek ayırmayı ertelemesine izin verir.

Bu bellek ayırma farkı da bind->listen->acceptdöngü içinde kendini gösterir . Libuv ile, uv_listenbir bağlantı kabul edilmeye hazır olduğunda kullanıcının geri aramasını çağıracak bir olay döngüsü oluşturur. Bu, uygulamanın, bir bağlantı denenene kadar istemcinin tahsisini ertelemesine izin verir. Öte yandan, Boost.Asio listensadece durumunu değiştirir acceptor. async_acceptBağlantı etkinlik için dinler ve akran gerektirir çağrılan önce tahsis edilecek.


Verim

Ne yazık ki, libuv ve Boost.Asio'yu karşılaştırmak için somut bir kıyaslama numaram yok. Ancak, gerçek zamanlı ve gerçek zamanlıya yakın uygulamalarda kütüphaneleri kullanarak benzer bir performans gözlemledim. Eğer sert sayılar isteniyorsa, libuv'un karşılaştırma testi başlangıç ​​noktası olarak kullanılabilir.

Ayrıca, gerçek darboğazları tanımlamak için profil oluşturma yapılırken, bellek ayırmalarına dikkat edin. Libuv için bellek ayırma stratejisi öncelikli olarak ayırıcı geri araması ile sınırlıdır. Öte yandan, Boost.Asio'nun API'sı bir ayırıcı geri aramasına izin vermez ve bunun yerine ayırma stratejisini uygulamaya aktarır. Ancak, Boost.Asio'daki işleyiciler / geri çağrılar kopyalanabilir, ayrılabilir ve yeniden konumlandırılabilir. Boost.Asio, uygulamaların işleyiciler için bir bellek ayırma stratejisi uygulamak amacıyla özel bellek ayırma işlevleri sağlamasına olanak tanır .


Olgunluk

Boost.Asio

Asio'nun gelişimi en az OCT-2004'e dayanıyor ve 20 günlük emsal incelemesinden sonra 22-MAR-2006'da 1.35'e yükseltildi. Ayrıca TR2 için Ağ Kitaplığı Önerisi için başvuru uygulaması ve API işlevi de görüyordu . Boost.Asio'nun yararlılığı kullanıcıdan kullanıcıya değişse de, oldukça fazla miktarda dokümana sahiptir .

API ayrıca oldukça tutarlı bir hisse sahiptir. Ayrıca, zaman uyumsuz işlemler işlemin adında açıktır. Örneğin accept, eşzamanlı engelleme ve async_accepteşzamansızdır. API, yaygın bir G / Ç görevi için, örneğin bir akış okunana kadar \r\nokumak için ücretsiz işlevler sağlar . Ayrıca ip::address_v4::any(), "tüm arabirimler" adresinin temsil edilmesi gibi ağa özgü bazı ayrıntıların gizlenmesine de dikkat edilmiştir 0.0.0.0.

Son olarak, Boost 1.47+, hata ayıklama sırasında yararlı olabileceği kanıtlanan işleyici izleme ve C ++ 11 desteğini sağlar.

libuv

Github grafiklerine dayanarak, Node.js'nin gelişimi en az FEB-2009'a ve libuv'un geliştirme tarihi MAR-2011'e dayanıyor . Uvbook bir libuv tanıtımı için harika bir yerdir. API belgeleri burada .

Genel olarak, API oldukça tutarlı ve kullanımı kolaydır. Karışıklık kaynağı olabilecek bir anomali, uv_tcp_listenbir izleyici döngüsü oluşturmasıdır. Bu, gözlemci döngüsünün ömrünü kontrol etmek için genellikle bir uv_*_startve bir uv_*_stopçift ​​fonksiyonu olan diğer gözlemcilerden farklıdır . Ayrıca, bazı uv_fs_*operasyonların makul miktarda argümanı vardır (7'ye kadar). Senkronize ve senkronize olmayan davranış bir geri çağırma (son argüman) mevcudiyetinde belirlenirken, senkron davranışın görünürlüğü azaltılabilir.

Son olarak, libuv taahhüt tarihine hızlı bir bakış , geliştiricilerin çok aktif olduğunu gösterir.


2
Teşekkürler dostum! Mükemmel cevap! Daha kapsamlı bir şey düşünemiyorum :)
Viet

1
Cevabından çok memnunum, size ödül ile ödüllendirdim :) SO'nun kendisi için en iyi cevaba karar vermesine izin verin.
Viet

28
İnanılmaz cevap. Bu, hem üst düzey resmi hem de ayrıntılardaki spesifik, önemli farklılıkları (örneğin, diş çekme / olay döngüsü gibi) kapsar. Çok teşekkür ederim!
oberstet

1
@oberstet: Hayır. Cevabı, libuv operasyonlarının çoğunun bire bir olduğunu belirtmek için güncelledim. Bununla birlikte, libuv birden fazla uv_async_sendçağrı biriktirebilir ve hepsini tek bir geri çağrı ile yönetebilir. Bu belgelenmiştir burada . Ayrıca herkese teşekkürler.
Tanner Sansbury

2
Boost.Asio'daki olay döngüsünde dahili kilitleme, performans açısından korkutucu görünüyor. Kilitsiz libuv'a nasıl benzer bir performans gösterebilir? Belki de performans bölümüne bir uyarı ifadesi eklemek yardımcı olabilir.
zeodtr

46

Tamam. Her iki kütüphaneyi kullanma konusunda da deneyimim var ve bazı şeyleri temizleyebilirim.

Birincisi, kavramsal bir bakış açısından, bu kütüphaneler tasarımda oldukça farklıdır. Farklı mimarileri var, çünkü farklı ölçeklerde. Boost.Asio, TCP / UDP / ICMP protokolleri, POSIX, SSL vb. İle kullanılması amaçlanan büyük bir ağ kütüphanesidir. Libuv sadece çapraz platform çekilebilmesi için bir tabakadır IOCP ağırlıklı, node.js için. Bu nedenle libuv işlevsel olarak Boost.Asio'nun bir alt kümesidir (ortak özellikler yalnızca TCP / UDP Soketleri iş parçacığı, zamanlayıcıları). Bu durumda, bu kütüphaneleri sadece birkaç kriter kullanarak karşılaştırabiliriz:

  1. Node.js - Libuv ile entegrasyon oldukça iyidir çünkü bu amaçlanmıştır (bunu tamamen entegre edebiliriz ve örneğin bulut gibi azure gibi tüm yönleriyle kullanabiliriz). Ancak Asio, Node.js olay kuyruğu odaklı ortamdaki neredeyse aynı işlevselliği de uygular.
  2. IOCP Performansı - Büyük farklılıklar göremedim, çünkü bu kütüphanelerin ikisi de temel OS API'sını soyutlıyor. Ancak bunu farklı bir şekilde yapıyorlar: Asio, şablonlar ve bazen TMP gibi C ++ özelliklerini yoğun bir şekilde kullanıyor. Libuv yerel bir C kütüphanesidir. Ancak yine de Asio'nun IOCP'nin gerçekleştirilmesi çok etkilidir. Asio'daki UDP soketleri yeterince iyi değil, onlar için libuv kullanmak daha iyidir.

    Yeni C ++ özellikleriyle entegrasyon: Asio daha iyidir (Asio 1.51, C ++ 11 asenkron modelini, hareket semantiğini, değişken şablonlarını yaygın olarak kullanır). Olgunluk açısından, Asio iyi belgelere sahip daha istikrarlı ve olgun bir projedir (eğer libuv ile karşılaştırırsanız) üstbilgilerin açıklaması), İnternet'te birçok bilgi (video görüşmeleri, bloglar: http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg = 1 , vb.) Ve hatta kitaplar (profesyoneller için değil, yine de: http://en.highscore.de/cpp/boost/index.html ). Libuv'un sadece bir çevrimiçi kitabı var (aynı zamanda iyi) http://nikhilm.github.com/uvbook/index.htmlve birkaç video görüşmesi, bu yüzden tüm sırları bilmek zor olacak (bu kütüphane çok fazla var). İşlevlerle ilgili daha ayrıntılı tartışma için aşağıdaki yorumlarıma bakın.

Sonuç olarak, her şeyin sizin amaçlarınıza, projenize ve ne yapmak istediğinize bağlı olduğunu söylemeliyim.


11
Önemli olan teknik beceri ve deneyiminizdir. Küba'dan nazik selamlar.
dsign

2
Asio belgeleri hariç tüm hususlarınızı kabul ediyorum. Resmi belgeler bu harika kütüphaneye adalet vermiyor. Diğer dokümanlar demet ve çok yararlı bulduğum yazar bir destek con konuşma vardır. Ve Asio için bir kitapla karşılaşmadım. Bunu cevabınıza bağlayabilir misiniz? Çok yardımcı olacak.
Vikas

@vikas Evet Belgelerin zayıf ve bazen çelişkili olduğuna katılıyorum ama libuv ile karşılaştırmak başlamak için güzel. bilgileri)
Oleksandr Karaberov

Ne demek "libuv işlevsel olarak Boost.Asio (TCP / UDP / Soketler ve iş parçacıkları) alt kümesi"? İçindekiler'e göre nikhilm.github.com/uvbook/index.html libuv daha geniş bir uygulamaya sahiptir ve daha sonra güçlendirir :: asio.
Sergei Nikulov

7
@AlexanderKaraberov ASIO'nun UDP ile yaşadığı sorunları genişletebilir misiniz?
Bruno Martinez


2

Taşınabilirlik durumunu ekleme: Bu yanıtı yayınladığım ve kendi girişimlerime göre:

  • Boost.ASIO'nun iOS ve Android için resmi bir desteği yoktur, örneğin derleme sistemi kutudan çıktığı gibi iOS için çalışmaz.
  • libuv, iOS ve Android için kolayca oluşturulur ve doğrudan dokümanlarında Android için resmi destek sağlar . Autotools tabanlı projeler için kendi genel iOS derleme komut dosyam sorunsuz çalışıyor.

Bazel boost oluşturma kurallarını kullanarak bazel kullanarak iOS ve andriod için bir çapraz platform çerçevesi oluşturmak oldukça kolaydır.
nnrales
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.