我感兴趣的方面有:
范围/功能 性能 成熟
我感兴趣的方面有:
范围/功能 性能 成熟
当前回答
一个巨大的不同是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
其他回答
一个巨大的不同是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
添加可移植性状态:在发布这个答案时,根据我自己的尝试:
提振。ASIO没有iOS和Android的官方支持,例如,它的构建系统不能在iOS上开箱即用。 libuv很容易在iOS和Android上构建,在他们的文档中有对Android的官方支持。我自己的通用iOS构建脚本用于基于autotools的项目,没有任何问题。
范围
提振。Asio是一个c++库,最初专注于网络,但它的异步I/O功能已经扩展到其他资源。此外,使用Boost。Asio是Boost库的一部分,它的范围被略微缩小,以防止与其他Boost库重复。例如,Boost。Asio不像Boost那样提供线程抽象。线程已经提供了一个。
另一方面,libuv是一个C库,被设计为Node.js的平台层。它提供了Windows上的IOCP, macOS上的kqueue和Linux上的epoll的抽象。此外,它的范围似乎略有增加,包括抽象和功能,如线程、线程池和线程间通信。
At their core, each library provides an event loop and asynchronous I/O capabilities. They have overlap for some of the basic features, such as timers, sockets, and asynchronous operations. libuv has a broader scope, and provides additional functionality, such as thread and synchronization abstractions, synchronous and asynchronous file system operations, process management, etc. In contrast, Boost.Asio's original networking focus surfaces, as it provides a richer set of network related capabilities, such as ICMP, SSL, synchronous blocking and non-blocking operations, and higher-level operations for common tasks, including reading from a stream until a newline is received.
特性列表
以下是对一些主要功能的简单并列比较。因为开发者使用Boost。Asio通常有其他可用的Boost库,我选择考虑额外的Boost库,如果它们要么直接提供,要么实现起来很简单。
libuv Boost Event Loop: yes Asio Threadpool: yes Asio + Threads Threading: Threads: yes Threads Synchronization: yes Threads File System Operations: Synchronous: yes FileSystem Asynchronous: yes Asio + Filesystem Timers: yes Asio Scatter/Gather I/O[1]: no Asio Networking: ICMP: no Asio DNS Resolution: async-only Asio SSL: no Asio TCP: async-only Asio UDP: async-only Asio Signal: Handling: yes Asio Sending: yes no IPC: UNIX Domain Sockets: yes Asio Windows Named Pipe: yes Asio Process Management: Detaching: yes Process I/O Pipe: yes Process Spawning: yes Process System Queries: CPU: yes no Network Interface: yes no Serial Ports: no yes TTY: yes no Shared Library Loading: yes Extension[2]
1. 分散/收集I / O。
2. 提振。扩展从未提交给Boost进行审查。如此处所述,作者认为它是完整的。
事件循环
而libuv和Boost。Asio提供事件循环,两者之间有一些细微的区别:
While libuv supports multiple event loops, it does not support running the same loop from multiple threads. For this reason, care needs to be taken when using the default loop (uv_default_loop()), rather than creating a new loop (uv_loop_new()), as another component may be running the default loop. Boost.Asio does not have the notion of a default loop; all io_service are their own loops that allow for multiple threads to run. To support this Boost.Asio performs internal locking at the cost of some performance. Boost.Asio's revision history indicates that there have been several performance improvements to minimize the locking.
Threadpool
libuv's provides a threadpool through uv_queue_work. The threadpool size is configurable via the environment variable UV_THREADPOOL_SIZE. The work will be executed outside of the event loop and within the threadpool. Once the work is completed, the completion handler will be queued to run within the event loop. While Boost.Asio does not provide a threadpool, the io_service can easily function as one as a result of io_service allowing multiple threads to invoke run. This places the responsibility of thread management and behavior to the user, as can be seen in this example.
线程和同步
Libuv提供了线程和同步类型的抽象。 提振。线程提供了线程和同步类型。这些类型中的许多都密切遵循c++ 11标准,但也提供了一些扩展。作为Boost的结果。Asio允许多个线程运行单个事件循环,它提供了一种方法来创建事件处理程序的顺序调用,而无需使用显式的锁定机制。
文件系统操作
libuv provides an abstraction to many file system operations. There is one function per operation, and each operation can either be synchronous blocking or asynchronous. If a callback is provided, then the operation will be executed asynchronously within an internal threadpool. If a callback is not provided, then the call will be synchronous blocking. Boost.Filesystem provides synchronous blocking calls for many file system operations. These can be combined with Boost.Asio and a threadpool to create asynchronous file system operations.
网络
libuv supports asynchronous operations on UDP and TCP sockets, as well as DNS resolution. Application developers should be aware that the underlying file descriptors are set to non-blocking. Therefore, native synchronous operations should check return values and errno for EAGAIN or EWOULDBLOCK. Boost.Asio is a bit more rich in its networking support. In addition many of the features libuv's networking provides, Boost.Asio supporting SSL and ICMP sockets. Furthermore, Boost.Asio provides synchronous blocking and synchronous non-blocking operations, into addition to its asynchronous operations. There are numerous free standing functions that provide common higher-level operations, such as reading a set amount of bytes, or until a specified delimiter character is read.
信号
Libuv通过其uv_signal_t类型和uv_signal_*操作提供了抽象终止和信号处理。 提振。Asio不提供要kill的抽象,但它的signal_set提供了信号处理。
IPC
libuv通过单个uv_pipe_t类型抽象Unix域套接字和Windows命名管道。 提振。Asio将两者分开为local::stream_protocol::socket或local::datagram_protocol::socket和windows::stream_handle。
API的差异
虽然api因语言而异,但这里有几个关键的区别:
操作和处理程序关联
在提高。Asio,在操作和处理程序之间存在一对一的映射。例如,每个async_write操作将调用WriteHandler一次。许多libuv操作和处理程序都是如此。然而,libuv的uv_async_send支持多对一映射。多个uv_async_send调用可能导致uv_async_cb被调用一次。
调用链vs. Watcher循环
When dealing with task, such as reading from a stream/UDP, handling signals, or waiting on timers, Boost.Asio's asynchronous call chains are a bit more explicit. With libuv, a watcher is created to designate interests in a particular event. A loop is then started for the watcher, where a callback is provided. Upon receiving the event of interests, the callback will be invoked. On the other hand, Boost.Asio requires an operation to be issued each time the application is interested in handling the event.
为了说明这种区别,这里有一个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" );
}
内存分配
As a result of the asynchronous call chains in Boost.Asio and the watchers in libuv, memory allocation often occurs at different times. With watchers, libuv defers allocation until after it receives an event that requires memory to handle. The allocation is done through a user callback, invoked internal to libuv, and defers deallocation responsibility of the application. On the other hand, many of the Boost.Asio operations require that the memory be allocated before issuing the asynchronous operation, such as the case of the buffer for async_read. Boost.Asio does provide null_buffers, that can be used to listen for an event, allowing applications to defer memory allocation until memory is needed, although this is deprecated.
This memory allocation difference also presents itself within the bind->listen->accept loop. With libuv, uv_listen creates an event loop that will invoke the user callback when a connection is ready to be accepted. This allows the application to defer the allocation of the client until a connection is being attempted. On the other hand, Boost.Asio's listen only changes the state of the acceptor. The async_accept listens for the connection event, and requires the peer to be allocated before being invoked.
性能
不幸的是,我没有任何具体的基准数据来比较libuv和Boost.Asio。但是,我在实时和近实时应用程序中使用这些库时,观察到类似的性能。如果需要硬数字,libuv的基准测试可以作为起点。
Additionally, while profiling should be done to identify actual bottlenecks, be aware of memory allocations. For libuv, the memory allocation strategy is primarily limited to the allocator callback. On the other hand, Boost.Asio's API does not allow for an allocator callback, and instead pushes the allocation strategy to the application. However, the handlers/callbacks in Boost.Asio may be copied, allocated, and deallocated. Boost.Asio allows for applications to provide custom memory allocation functions in order to implement a memory allocation strategy for handlers.
成熟
提振。Asio
Asio的开发至少可以追溯到2004年10月,经过20天的同行评审后,于2006年3月22日被纳入Boost 1.35。它还作为TR2网络库提案的参考实现和API。提振。Asio有相当数量的文档,尽管它的用处因用户而异。
API也有相当一致的感觉。此外,异步操作在操作名称中是显式的。例如,accept是同步阻塞,async_accept是异步阻塞。该API为常见的I/O任务提供了免费函数,例如,从流中读取直到读取\r\n。还注意隐藏一些特定于网络的细节,例如ip::address_v4::any()表示0.0.0.0的“所有接口”地址。
最后,Boost 1.47+提供了处理程序跟踪,这在调试时被证明是有用的,以及c++ 11支持。
libuv
根据他们的github图表,Node.js的开发可以追溯到至少2009年2月,libuv的开发可以追溯到2011年3月。uvbook是一个介绍libuv的好地方。API文档在这里。
Overall, the API is fairly consistent and easy to use. One anomaly that may be a source of confusion is that uv_tcp_listen creates a watcher loop. This is different than other watchers that generally have a uv_*_start and uv_*_stop pair of functions to control the life of the watcher loop. Also, some of the uv_fs_* operations have a decent amount of arguments (up to 7). With the synchronous and asynchronous behavior being determined on the presence of a callback (the last argument), the visibility of the synchronous behavior can be diminished.
最后,快速浏览一下libuv提交历史就会发现开发人员非常活跃。
好的。我有一些使用这两个库的经验,可以澄清一些事情。
First, from a conceptual view-point these libraries are quite different in design. They have different architectures, because they are of different scale. Boost.Asio is a large networking library aimed to be used with TCP/UDP/ICMP protocols, POSIX, SSL and so on. Libuv is just a layer for cross-platform abstraction of IOCP for Node.js, predominantly. So libuv is functionally a subset of Boost.Asio (common features only TCP/UDP Sockets threads,timers). Being that the case, we can compare these libraries using only few criteria:
Integration with Node.js - Libuv is considerably better because it is aimed for this (we can fully integrate it and use in all aspects, for instance, cloud e.g. windows azure). But Asio also implements almost the same functionality as in Node.js event queue driven environment. IOCP Performance - I couldn't see great differencies, because both these libraries abstract underlying OS API. But they do it in a different way: Asio heavily uses C++ features such as templates and sometimes TMP. Libuv is a native C-library. But nevertheless Asio realisation of IOCP is very efficient. UDP sockets in Asio are not good enough it is better to use libuv for them.Integration with new C++ features: Asio is better (Asio 1.51 extensively use C++11 asynchronous model, move semantics, variadic templates).In regard to maturity, Asio is a more stable and mature project with good documentation (if compare it to libuv headers description), a lot of information across the Internet (video talks, blogs: http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=1 ,etc.) and even books (not for professionals but nevertheless: http://en.highscore.de/cpp/boost/index.html ). Libuv has only one online book (but also good) http://nikhilm.github.com/uvbook/index.html and several video talks, so it will be difficult to know all the secrets (this library has a lot of them). For more specific discussion of functions see my comments below.
作为结论,我应该说这一切都取决于你的目的,你的项目和你具体想做什么。