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。 应用程序开发人员应该知道底层文件描述符被设置为非阻塞。 因此,本地同步操作应检查
EAGAIN
或EWOULDBLOCK
返回值和errno 。 - Boost.Asionetworking支持有点丰富。 另外libuv的networking提供了许多function,Boost.Asio支持SSL和ICMP套接字。 此外,除了asynchronous操作,Boost.Asio还提供了同步阻塞和同步非阻塞操作。 有许多独立函数可以提供常见的高级操作,例如读取一定数量的字节,或直到读取指定的分隔符。
信号
- libuv使用
uv_signal_t
types和uv_signal_*
操作提供抽象kill
和信号处理。 目前 ,只有默认的事件循环支持信号。 - Boost.Asio并不提供一个抽象来
kill
,但它的signal_set_service
提供信号处理。
IPC
- libuv通过一个
uv_pipe_t
types来抽象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_read
的buffer
。 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.0
的ip::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_*_start
和uv_*_stop
function的观察者不同,以控制观察者循环的寿命。 此外,一些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套接字线程,定时器)。 正因为如此,我们可以只用几个标准比较这些库:
- 与Node.js集成 – Libuv是相当好的,因为它是针对这个(我们可以完全整合和使用在所有方面,例如,云,如Windows Azure)。 但是,Asio也实现了与Node.js事件队列驱动环境中几乎相同的function。
- 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