libuv与Boost / ASIO相比如何?

我会对如下方面感兴趣:

  • 范围/function
  • 性能
  • 到期

范围

Boost.Asio是一个以关注networking为开始的C ++库,但其asynchronousI / Ofunction已扩展到其他资源。 此外,Boost.Asio是Boost库的一部分,其范围略有缩小,以防止与其他Boost库重复。 例如,Boost.Asio不会提供线程抽象,因为Boost.Thread已经提供了一个抽象。

另一方面, libuv是一个C库,被devise为node.js的平台层。 它提供了Windows的IOCP和Unix系统上的libev的抽象。 尽pipe如本文所述,努力消除自由。 此外,它的范围看起来好像略微增加了一些抽象和function,如线程,线程池和线程间通信。

在它们的核心,每个库提供一个事件循环和asynchronousI / Ofunction。 它们具有某些基本function的重叠,例如定时器,套接字和asynchronous操作。 libuv具有更广泛的范围,并提供了附加function,如线程和同步抽象,同步和asynchronous文件系统操作,进程pipe理等。相比之下,Boost.Asio的原有networking关注点,因为它提供了一组更丰富的networking相关function,如ICMP,SSL,同步阻塞和非阻塞操作,以及用于常见任务的更高级操作,包括从stream中读取直到接收到换行符为止。


function列表

以下是一些主要特征的简短比较。 由于使用Boost.Asio的开发人员经常有其他Boost库可用,所以我select考虑额外的Boost库,如果它们是直接提供的或者微不足道的实现。

                          libuv Boost
事件循环:是阿西奥
线程池:是的Asio +线程
线程:              
  线程:是线程
  同步:是线程
文件系统操作:
  同步:是文件系统
  asynchronous:是的Asio +文件系统
定时器:是的
分散/收集I / O [1] :没有Asio
联网:
   ICMP:没有Asio
   DNSparsing:Async-only Asio
   SSL:没有Asio
   TCP:Async-only Asio
   UDP:asynchronousAsio
信号:
  处理:是阿西奥
  发送:是的
 IPC:
   UNIX域套接字:是Asio
   Windows命名pipe道:是Asio
stream程pipe理:
  分离:是过程
   I / Opipe道:是过程
  产卵:是过程
系统查询:
   CPU:是的
  networking接口:是的
串行端口:不是
 TTY:是的
共享库加载:是扩展名[2] 

1. 分散/收集I / O。

2. Boost.Extension从未提交审查提升。 如此处所述,作者认为它是完整的。

事件循环

虽然libuv和Boost.Asio都提供了事件循环,但两者之间有一些细微的差别:

  • 虽然libuv支持多个事件循环,但它不支持从多个线程运行相同的循环。 因为这个原因,当使用默认循环( uv_default_loop() )时,需要注意,而不是创build一个新的循环( uv_loop_new() ),因为另一个组件可能正在运行默认循环。
  • Boost.Asio没有默认循环的概念; 所有的io_service都是自己的循环,允许多个线程运行。 为了支持这个Boost.Asio以一些性能为代价执行内部locking 。 Boost.Asio的修订历史表明,已经有几个性能改进来最小化locking。

线程池

  • libuv通过uv_queue_work提供一个uv_queue_work 。 线程池的大小是一个实现的细节,似乎不能通过APIconfiguration。 该工作将在事件循环之外和线程池内执行。 一旦工作完成,完成处理程序将排队在事件循环内运行。
  • 虽然Boost.Asio不提供线程池,但io_service可以很容易地作为io_service一个结果,允许多个线程调用run 。 这将线程pipe理和行为的责任交给了用户,正如在这个例子中可以看到的那样。

线程和同步

  • libuv提供了线程和同步types的抽象。
  • Boost.Thread提供了一个线程和同步types。 这些types中的许多types都严格遵循C ++ 11标准,但也提供了一些扩展。 由于Boost.Asio允许多个线程运行单个事件循环,因此它提供了strands作为创build事件处理程序的顺序调用而不使用显式locking机制的手段。

文件系统操作

  • libuv提供了许多文件系统操作的抽象。 每个操作有一个函数,每个操作可以是同步阻塞或asynchronous的。 如果提供callback,那么该操作将在内部线程池内asynchronous执行。 如果没有提供callback,则该呼叫将被同步阻止。
  • Boost.Filesystem为许多文件系统操作提供了同步阻塞调用。 这些可以与Boost.Asio和一个线程池相结合来创buildasynchronous文件系统操作。

联网

  • libuv支持在UDP和TCP套接字上的asynchronous操作,以及DNSparsing。 应用程序开发人员应该知道底层文件描述符被设置为非阻塞。 因此,本地同步操作应检查EAGAINEWOULDBLOCK返回值和errno
  • Boost.Asionetworking支持有点丰富。 另外libuv的networking提供了许多function,Boost.Asio支持SSL和ICMP套接字。 此外,除了asynchronous操作,Boost.Asio还提供了同步阻塞和同步非阻塞操作。 有许多独立函数可以提供常见的高级操作,例如读取一定数量的字节,或直到读取指定的分隔符。

信号

  • libuv使用uv_signal_ttypes和uv_signal_*操作提供抽象kill和信号处理。 目前 ,只有默认的事件循环支持信号。
  • Boost.Asio并不提供一个抽象来kill ,但它的signal_set_service提供信号处理。

IPC

  • libuv通过一个uv_pipe_ttypes来抽象Unix域套接字和Windows命名pipe道 。
  • Boost.Asio将两者分离为local :: stream_protocol :: socket / local :: datagram_protocol :: socket和windows::stream_handle

API差异

虽然API基于单独的语言而不同,但是这里有一些关键的区别:

操作和处理程序协会

在Boost.Asio中,操作和处理程序之间有一对一的映射关系。 例如,每个async_write操作都会调用一次WriteHandler 。 许多libuv操作和处理程序都是如此。 但是,libuv的uv_async_send支持多对一的映射。 多个uv_async_send调用可能会导致uv_async_cb被调用一次。

呼叫链与Watcher循环

当处理任务时,比如读取stream/ UDP,处理信号或者等待定时器,Boost.Asio的asynchronous调用链更加清晰。 使用libuv,创build观察者来指定特定事件中的兴趣。 然后为观察者启动一个循环,在那里提供callback。 一旦收到兴趣事件,callback将被调用。 另一方面,Boost.Asio需要在每次应用程序有兴趣处理事件时发布操作。

为了帮助说明这种差异,下面是一个使用Boost.Asio的asynchronous读取循环,其中async_receive调用将被多次执行:

 void start() { socket.async_receive( buffer, handle_read ); ----. } | .----------------------------------------------' | .---------------------------------------. VV | void handle_read( ... ) | { | std::cout << "got data" << std::endl; | socket.async_receive( buffer, handle_read ); --' } 

这里是libuv的例子,每当观察者观察到套接字有数据时, handle_read被调用:

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

内存分配

由于Boost.Asio中的asynchronous调用链和libuv中的观察者,内存分配通常发生在不同的时间。 对于观察者,libuv会在接收到需要内存处理的事件之后才推迟分配。 分配是通过用户callback完成的,调用libuv内部,并延迟应用程序的解除分配责任。 另一方面,许多Boost.Asio操作要求在发出asynchronous操作之前分配内存,例如async_readbuffer 。 Boost.Asio提供了null_buffers ,可以用来侦听事件,允许应用程序延迟内存分配,直到需要内存为止。

这个内存分配差异也出现在bind->listen->accept循环中。 使用libuv, uv_listen创build一个事件循环,当连接准备好被接受时,将会调用用户callback。 这允许应用程序推迟客户端的分配,直到尝试连接。 另一方面,Boost.Asio的listen只会改变acceptor的状态。 async_accept监听连接事件,并要求在调用之前分配对等体。


性能

不幸的是,我没有任何具体的基准数字比较libuv和Boost.Asio。 但是,在实时和近实时应用程序中,我使用库来观察到类似的性能。 如果需要硬数,libuv的基准testing可能是一个起点。

另外,在分析时应该确定实际的瓶颈,注意内存分配。 对于libuv,内存分配策略主要限于分配器callback。 另一方面,Boost.Asio的API不允许分配器callback,而是将分配策略推送到应用程序。 但是,Boost.Asio中的处理程序/callback可能会被复制,分配和释放。 Boost.Asio允许应用程序提供自定义内存分配function,以实现处理程序的内存分配策略。


到期

Boost.Asio的

阿西欧的发展至less可以追溯到2004年10月,经过20天的同行评议,2006年3月22日,阿斯欧奥被纳入了1.35版本。 它也作为TR2networking库build议的参考实现和API。 Boost.Asio有相当数量的文档 ,虽然它的用处因用户而异。

API也有一个相当一致的感觉。 此外,asynchronous操作在操作名称中是显式的。 例如, accept是同步阻塞,而async_accept是asynchronous的。 API为通用I / O任务提供了免费的function,例如从stream中读取直到读取\r\n 。 还注意隐藏一些networking特定的细节,例如表示“所有接口”地址为0.0.0.0ip::address_v4::any()

最后,Boost 1.47+提供了处理程序跟踪function ,可以在debugging时certificate是有用的,同时也支持C ++ 11。

libuv

基于它们的github图,Node.js的开发至less可以追溯到2009年2月 ,而libuv的开发date到了2011年3月 。 uvbook是一个libuv介绍的好地方。 该API以详细标题的formslogging,但仍可以在某些区域使用贡献。

总的来说,API是相当一致的,易于使用。 一个可能成为混淆之处的exception是uv_tcp_listen创build一个观察者循环。 这与其他通常具有uv_*_startuv_*_stopfunction的观察者不同,以控制观察者循环的寿命。 此外,一些uv_fs_*操作有相当数量的参数(高达7)。 通过callback(最后一个参数)的存在来确定同步和asynchronous行为,可以减less同步行为的可见性。

最后,快速浏览一下libuv 提交历史logging ,发现开发人员非常活跃。

好。 我有一些使用这两个库的经验,可以清除一些事情。

首先,从概念上看,这些图书馆在devise上有很大的不同。 他们有不同的架构,因为他们规模不一样。 Boost.Asio是一个大型networking库,旨在与TCP / UDP / ICMP协议,POSIX,SSL等一起使用。 Libuv仅仅是一个跨平台的Node.js IOCP抽象层。 所以libuv在function上是Boost.Asio的一个子集(仅限于TCP / UDP套接字线程,定时器)。 正因为如此,我们可以只用几个标准比较这些库:

  1. 与Node.js集成 – Libuv是相当好的,因为它是针对这个(我们可以完全整合和使用在所有方面,例如,云,如Windows Azure)。 但是,Asio也实现了与Node.js事件队列驱动环境中几乎相同的function。
  2. IOCP性能 – 我看不出很大的差异,因为这两个库都抽象了底层的OS API。 但是他们用不同的方式来做:Asio主要使用C ++特性,比如模板,有时候也使用TMP。 Libuv是一个本地的C库。 但是,IOCP的Asio实现非常高效。 Asio中的UDP套接字不够好,最好使用libuv。

    与新的C ++function整合:Asio更好(Asio 1.51广泛使用C ++ 11asynchronous模式,移动语义,可变模板)。关于成熟度,Asio是一个更稳定和成熟的项目,具有良好的文档(如果与libuv标题说明),互联网上的大量信息(video讲座,博客: http ://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio? pg = 1等),甚至书籍(不是专业人士,但不过: http : //en.highscore.de/cpp/boost/index.html )。 Libuv只有一本在线书(也很好) http://nikhilm.github.com/uvbook/index.html和几个video讲座,所以很难知道所有的秘密(这个图书馆有很多); 。 有关函数的更多具体讨论,请参阅下面的评论。

作为结论,我应该说这一切都取决于你的目的,你的项目以及你打算做的具体事情。

一个巨大的区别是Asio的作者(Christopher Kohlhoff)正在把他的图书馆整理到C ++标准库中,参见http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2175 .pdf和http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4370.html