Answers:
Boost.Asio是一个C ++库,最初专注于网络,但其异步I / O功能已扩展到其他资源。此外,由于Boost.Asio是Boost库的一部分,因此其范围略为缩小,以防止与其他Boost库重复。例如,Boost.Asio将不提供线程抽象,因为Boost.Thread已经提供了线程抽象。
另一方面,libuv是一个C库,旨在作为Node.js的平台层。它为Windows 上的IOCP,macOS 上的kqueue和Linux上的epoll提供了抽象。此外,它的范围似乎有所扩大,以包含抽象和功能,例如线程,线程池和线程间通信。
每个库的核心都是事件循环和异步I / O功能。它们在某些基本功能上有重叠,例如计时器,套接字和异步操作。libuv具有更广泛的范围,并提供其他功能,例如线程和同步抽象,同步和异步文件系统操作,进程管理等。相比之下,Boost.Asio最初的网络关注重点在于它提供了一组更丰富的网络相关内容ICMP,SSL,同步阻止和非阻止操作等功能以及针对常见任务的更高级别操作,包括从流中读取直到接收到换行符。
这是一些主要功能的简要并排比较。由于使用Boost.Asio的开发人员经常会提供其他Boost库,因此,如果直接提供或实现起来很简单,我选择考虑其他Boost库。
libuv加速 事件循环:是Asio 线程池:是Asio +线程 线程: 线程:是的线程 同步:是线程 文件系统操作: 同步:是FileSystem 异步:是Asio +文件系统 计时器:是的Asio 分散/聚集I / O [1]:无Asio 联网: ICMP:没有Asio DNS解析:仅异步Asio SSL:无Asio TCP:仅异步Asio UDP:仅异步Asio 信号: 处理:是Asio 发送:是否 IPC: UNIX域套接字:是Asio Windows命名管道:是Asio 流程管理: 拆卸:是的过程 I / O管道:是进程 产生:是的过程 系统查询: CPU:是否 网络接口:是否 串行端口:否是 TTY:是的 共享库加载:是扩展[2]
1. 分散/聚集I / O。
2. Boost.Extension从未提交给Boost进行审查。如前所述这里,笔者认为它是完整的。
虽然libuv和Boost.Asio都提供事件循环,但两者之间还是有一些细微的区别:
uv_default_loop()
)时要格外小心,而不是创建新的循环(uv_loop_new()
),因为另一个组件可能正在运行默认循环。io_service
都是自己的循环,允许多个线程运行。为支持此功能,Boost.Asio会以牺牲一些性能为代价执行内部锁定。Boost.Asio的修订历史记录表明,已进行了一些性能改进,以最大程度地减少锁定。uv_queue_work
。线程池的大小可以通过环境变量进行配置UV_THREADPOOL_SIZE
。该工作将在事件循环之外和线程池中执行。工作完成后,完成处理程序将排队在事件循环内运行。io_service
由于io_service
允许多个线程调用,因此可以轻松地将其用作一个线程池run
。如本例所示,这将线程管理和行为的责任交给用户。EAGAIN
或EWOULDBLOCK
。kill
通过其uv_signal_t
类型和uv_signal_*
操作提供抽象和信号处理。kill
,但signal_set
提供信号处理。uv_pipe_t
。local::stream_protocol::socket
或local::datagram_protocol::socket
,和windows::stream_handle
。虽然仅基于语言,API有所不同,但这里有一些主要区别:
在Boost.Asio中,操作和处理程序之间存在一对一的映射。例如,每个async_write
操作将调用一次WriteHandler。对于许多libuv操作和处理程序来说都是如此。但是,libuv uv_async_send
支持多对一映射。多次uv_async_send
调用可能导致uv_async_cb被调用一次。
在处理任务(例如从流/ UDP读取,处理信号或等待计时器)时,Boost.Asio的异步调用链更加明确。使用libuv,可以创建观察者来指定特定事件的兴趣。然后为观察者启动一个循环,其中提供了回调。收到兴趣事件后,将调用回调。另一方面,Boost.Asio要求每次应用程序有兴趣处理事件时都发出一个操作。
为了帮助说明这种差异,这是一个带有Boost.Asio的异步读取循环,该async_receive
调用将被多次发出:
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 ); --'
}
这是libuv的相同示例,handle_read
每次观察者观察到套接字具有数据时都会调用该示例:
uv_read_start( socket, alloc_buffer, handle_read ); --.
|
.-------------------------------------------------'
|
V
void handle_read( ... )
{
fprintf( stdout, "got data\n" );
}
由于Boost.Asio中的异步调用链和libuv中的观察器,内存分配通常发生在不同的时间。对于观察者,libuv推迟分配,直到它收到需要内存处理的事件为止。分配是通过用户回调完成的,该回调在libuv内部调用,并推迟了应用程序的分配责任。另一方面,许多Boost.Asio操作要求在发出异步操作之前先分配内存,例如buffer
for 的情况async_read
。Boost.Asio确实提供了null_buffers
,可用于侦听事件,从而允许应用程序将内存分配推迟到需要内存时进行,尽管已不建议这样做。
这种内存分配差异也会在bind->listen->accept
循环中出现。使用libuv,uv_listen
创建一个事件循环,当准备好接受连接时将调用用户回调。这允许应用程序延迟客户端的分配,直到尝试连接为止。另一方面,Boost.Asio listen
仅更改的状态acceptor
。该async_accept
用于连接事件监听,并要求对方在被调用之前进行分配。
不幸的是,我没有任何具体的基准数字来比较libuv和Boost.Asio。但是,我观察到在实时和近实时应用程序中使用库的性能类似。如果需要硬数字,可以使用libuv的基准测试作为起点。
此外,虽然应该进行概要分析以识别实际瓶颈,但要注意内存分配。对于libuv,内存分配策略主要限于分配器回调。另一方面,Boost.Asio的API不允许分配器回调,而是将分配策略推送到应用程序。但是,Boost.Asio中的处理程序/回调可以被复制,分配和释放。Boost.Asio允许应用程序提供自定义内存分配功能,以便为处理程序实现内存分配策略。
Asio的开发至少可以追溯到2004年10月,并且在经过20天的同行评审之后,于2006年3月22日被Boost 1.35接受。它还用作TR2网络图书馆提案的参考实现和API 。Boost.Asio具有大量文档,尽管其实用性因用户而异。
该API也具有相当一致的感觉。此外,异步操作在操作名称中是显式的。例如,accept
是同步阻塞,async_accept
是异步。API提供了用于常见I / O任务的免费功能,例如,从流\r\n
中读取直到读取a。还已经注意隐藏一些特定于网络的细节,例如ip::address_v4::any()
表示的“所有接口”地址0.0.0.0
。
最后,Boost 1.47+提供了处理程序跟踪,它在调试以及C ++ 11支持时都非常有用。
根据他们的github图,Node.js的开发至少可以追溯到FEB-2009,而libuv的开发可以追溯到MAR-2011。该uvbook是一个libuv引进一个伟大的地方。API文档在这里。
总体而言,该API相当一致且易于使用。可能引起混乱的一个异常是uv_tcp_listen
创建观察者循环。这不同于通常具有uv_*_start
和uv_*_stop
对功能来控制观察程序循环寿命的其他观察程序。同样,某些uv_fs_*
操作具有相当数量的参数(最多7个)。通过根据回调(最后一个参数)的存在确定同步和异步行为,可以减少同步行为的可见性。
最后,快速浏览一下libuv 提交历史记录,表明开发人员非常活跃。
uv_async_send
调用,并通过单个回调处理所有这些调用。它记录在这里。另外,谢谢大家。
好。我在使用这两个库方面都有一定的经验,可以解决一些问题。
首先,从概念上来看,这些库在设计上有很大的不同。它们具有不同的体系结构,因为它们的规模不同。Boost.Asio是一个大型网络库,旨在与TCP / UDP / ICMP协议,POSIX,SSL等一起使用。Libuv主要是Node.js 的IOCP跨平台抽象的一层。因此,libuv从功能上讲是Boost.Asio的子集(常见的功能仅是TCP / UDP套接字线程,计时器)。在这种情况下,我们可以仅使用以下几个标准来比较这些库:
与新的C ++功能集成:Asio更好(Asio 1.51广泛使用C ++ 11异步模型,移动语义,可变参数模板)就成熟度而言,Asio是一个更加稳定和成熟的项目,具有良好的文档记录(如果与libuv进行比较)标头说明),互联网上的大量信息(视频讲座,博客: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以及几个视频讲座,因此很难知道所有秘密(这个库有很多秘密)。有关功能的更具体讨论,请参见下面的评论。
最后,我应该说,这完全取决于您的目的,您的项目以及您打算做什么。
一个巨大的不同是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