Blog.csdn.net/lijinqi1987…

 

Three network libraries, Libevent, libev, and libuv, are all c language Asynchronousevent libraries.

The Asynchronous Event library essentially provides Asynchronous Event Notification (AEN). The asynchronous event notification mechanism calls the corresponding callback function to process the event.

Events: Events are the core of the asynchronous Event notification mechanism, such as FD events, timeout events, signal events, timer events. An event is sometimes called an EventHandler (EventHandler), which is more figurative because the Handler itself represents both the data (or the address of the data) and the processing method (the callback function), more in object-oriented thinking.

EventLoop: Waits for and dispatches events. Event loops are used to manage events.

For applications, these are just an asynchronous event library provides API, encapsulates the asynchronous event library interaction with the operating system, asynchronous event library will choose an operating system provides the mechanism to achieve a certain events, such as using the Unix/Linux platform epoll mechanism to realize the network IO events, in a variety of mechanisms can be use at the same time, The asynchronous event library uses an optimal mechanism.

 

Compare these three libraries:

Libevent: The best-known, most widely used, and long-established cross-platform event library;

Libev: Simpler design and better performance than Libevent, but not good enough for Windows;

Libuv: The node development process needs a cross-platform event library, they preferred libev, but also to support Windows, so repackaged a set, Linux using Libev implementation, Windows using IOCP implementation;

 

Influence on Github:

It can be seen that Libuv has the greatest influence at present, followed by Libevent, which attracts less attention.

 

Priority, event loop, thread safety dimension comparison

 

features                        libevent libev libuv
* * * *priority Activated events are grouped in a priority queue. By default, the priorities of all events are the same. You can set the priorities of events so that they are processed first The activation time is also managed through the priority queue, and the event priority can also be set There is no concept of priority and events are accessed in a fixed order
 Event loop Event_base is used to manage events Activated events are organized in a priority queue. By default, the priorities of all events are the same. You can set the priorities of events so that they are processed first
 Thread safety Both event_base and loop are not thread-safe. An event_base or loop instance can only be accessed in one thread of the user (usually the main thread). Events registered to event_base or loop are serially accessed. The activated events are accessed in priority order and their callbacks are executed. So there is no parallelism in the execution of the callback function when only one event_base or loop is used

 

 

 

 

Types of events

 

type libevent libev libuv
IO fd io fs_event
Mono clock timer timer timter
Wall clock periodic
signal signal signal signal
Process control child process
File the stat stat fs_poll
Idle events that are executed for each loop idle idle
Execute before loop block prepare prepare
Execute after loop BLCCK check check
Nested loop embed
fork fork
Loop cleanup before destruction cleanup
Operates on loop in another thread async async
stream ( tcp, pipe, tty ) stream ( tcp, pipe, tty ) stream ( tcp, pipe, tty ) stream ( tcp, pipe, tty )

This comparison is more meaningful for Libev and Libuv, and for Libevent, a lot of it has to do with its design ideas. Embed in Libev is rarely used, and libuv doesn’t have it. Cleanup can be completely replaced with async_exit in libuv; Libuv has no fork events.

 

 

 

 

portability

All three libraries support Linux, *BSD, Mac OS X, Solaris, and Windows

 

type libevent libev libuv
dev/poll (Solaris) y y y
event ports y y y
kqueue (*BSD) y y y
POSIX select y y y
Windows select y y y
Windows IOCP y N y
poll y y y
epoll y y y

 

 

 

For Unix/Linux platforms, there is no big difference, epoll is preferred, for Windows, libevent, Libev both use SELECT to detect and distribute events (no I/O), and Libuv uses IOCP under Windows. Libevent has a socket handle that uses IOCP for reading and writing on Windows. Libev has nothing like that. But libevent’s IOCP support isn’t very good either. So if you’re on Windows, use native IOCP for I/O, or use Libuv.

 

Asynchronous architecture programming principles

1. The callback function should not be executed for a long time, because a loop may contain other events, especially some timers with high accuracy requirements.

2. Try to use the cached time in the library. Sometimes you need to perform operations such as timeout according to the time difference. Of course, it would be nice to be able to use the timer in the library.

 

 

Reference: zheolong. Making. IO/blog/libeve…

    cpp.libhunt.com/

 

 

 

libevent

libev

libuv

node.js

 

The difference between a library and a framework is that ASIO is designed as a set of libraries rather than a framework.

What is a framework? A framework is a set of fixed programming structure of the library, any user to use it, must follow the framework library structure design, such as MFC OnOK, OnXXX, or ACE ACE_Handler:: handLE_XXX_YYy, etc., Users implement their own processing in the virtual functions of these derived classes.

What is a tool library? A library is a set of apis, not a framework, that users can use without having to fill in code from a specified place. The framework of the application is up to the user. Similar libraries are STL in C++ and standard library in C, which never provide a programming framework, but only provide utility functions that allow users to organize their program structure correctly through these utility functions.

The framework is very restrictive and not flexible enough

 

www.avboost.com/t/topic/654

 

select

Select is too slow.

Under this background, IBM big Brother led MS big brother to do IOCP first. However, open source people have open source practices. Under the influence of NIH syndrome, BSD people dare to be despised by the world and invent Kqueue. Also under the influence of NIH syndrome, a bunch of M* monkeys in Linux created epoll.

Split, make a headache.

So programmers are in urgent need of a magic weapon of the omnipotent magic weapon, the three magic weapons to the royal. ACE was the first to stand out.

ACE is overly complex, even more complex than the object it tries to encapsulate

Libevent is, as the name suggests, an asynchronous event framework.

Libevent is a good library to simplify simple problems and simplify asynchronous network programming.

However, libevent was born because of design flaws, such as the use of global variables and the inability of the timer to handle time jumps. Libev was created to overcome the shortcomings of Libevent. But will Libev get better?

 

Libev comes out with a grudge against Libevent.

 

Writing asynchronous programs, the two most needed abstraction capabilities, one is coroutines, and the other is function objects, including anonymous function objects, namely lambda. C None at all. Function objects are necessary to implement closures. If there is no function object, it can only be completed in the form of void* Pointers, which is tedious and error-prone.

 

Despite C’s shortcomings, Libev has yet to be weighed down by C’s shortcomings because it does not support IOCP. So Libuv came out to clean libev’s ass.

Libuv is as high as C’s asynchronous library can go. It completely touches the bottleneck of C language. Fortunately, Libuv is only the base library of NodeJS, and the upper layer software is transferred to javascript language to escape the shackles of C.

 

ASIO came out of nowhere

On the largest island on earth, another boy began to read the ACE. At that time, there was no libuv, no libev, no libevent. There is only ACE.

Speaking at a developer conference, He once again revealed that the web library should not be used as a framework, but as a Lego building block, like the system’s API. The ACE was made into a frame, which was equally inappropriate.

 

buffers

With closure support, memory management becomes much easier. ASIO does not manage memory itself. All I/O operations submit only references to user-managed memory, called Buffers. Asio :: Buffers references user-submitted memory, and it is the user’s responsibility to keep this memory valid throughout the IO. But it’s not hard! Because the callback is a closure. Holding memory through closures, as long as ASIO hasn’t called back, the closure is in, the closure is in. Asio does not remove the closure until after the callback is called. So responsibility for resource management can be left to closures, which can control memory precisely with smart Pointers. Not GC, a thousand times better than GC! Thanks to the RAII mechanism of c++, no memory leaks!

 

Asio uses the ProActor mode, and the Windows IOCP itself is the embodiment of this mode

In the design of high performance server concurrency model,Reactor and Proactor are two frequently used design patterns. The former is used for synchronous I/O, and the latter is used for asynchronous I/O. The former notifies the user when THE I/O operation is ready and then the user takes the actual I/O operation, and the latter notifies the user after the I/O operation is completed.

The IOCP design is a perfect example of the Proactor pattern, while ePoll is easy to implement the Reactor pattern. Asio is designed to be cross-platform and uses Epoll for Linux, which I remember is asynchronous IO support is not as complete as Windows (see the difference between IOCP and epoll models), so how does ASIO implement proActor mode with epoll mechanism In asIO, there should be a loop called epoll_wait to do something for the user when an I/O event is ready Copy to our submitted buffer) and call our handler when the operation is done.

 

Libevent is essentially synchronous, because if you look at select and epoll wrapped underneath it, it’s still a while loop asking if it’s ready, and the main difference with asynchronous synchronous IO is that when an application initiates an IO, The kernel does not wait for the KERNEL TO complete the I/O operation. The kernel notifies the application when it completes the I/O operation. This is the key difference between synchronous and asynchronous. In addition, the Reactor model is a synchronous model, isn’t it?

If you understand the underlying select or epoll. You’ll see that it’s actually synchronized. There is a while loop that waits for the event to fire the condition. If the conditions are met, the corresponding callback function is called. So it’s essentially synchronous. But with an asynchronous face

Libevent is itself a Reactor, which is synchronous. However, libevent’s bufferevent is implemented as a Proactor by a Reactor, so libevent is asynchronous

 

 

 

 

Libuv and Libev, two I/O libraries with similar names, have recently had the pleasure of writing something with both libraries. Here is my subjective statement of the similarities and differences between the two libraries.

The topic of high performance network programming has been discussed too much. Asynchronous, asynchronous, asynchronous. Whether epoll or Kqueue, asynchrony is always a topic. Libuv is asynchronous and LIBEV is synchronous multiplexing of IO.

Libev is a simple package for system I/O reuse. Basically, it solves the problem of different apis between epoll, Kqueuq, and SELECT. Ensure that programs written using liveV’s API can run on most * Nix platforms. However, the disadvantages of Libev are also obvious. As it basically encapsulates the Event Library, it is inconvenient to use it. For example, after an Accept (3) connection, you need to manually setnonblocking. EAGAIN, EWOULDBLOCK, and EINTER are detected when read or written from the socket. This is at the root of why most people find asynchronous programs hard to write.

Libuv is more sophisticated. Libuv is an I/O Library created by Joyent for Node. As a result, the biggest characteristic of Libuv is the callback everywhere. Basically, wherever blocking is possible, Libuv uses callback processing. This actually reduces the programmer’s workload considerably. Since libuv guarantees you something to do when the callback is called, handles such as EAGAIN and EWOULDBLOCK are not the programmer’s job and Libuv will silently do it for you.

Libev only tells you “XX socket can read/write, do it yourself” when a socket read/write event occurs. Often we need to allocate memory ourselves and call read(3) or write(3) in response to I/O events.

Libuv is a little more complicated and is described in two parts: read/write.

When the interface is readable, libuv calls your allocate Callback to allocate memory and write what is read. After reading, libuv will call the callback you set for the socket with the buffer in the argument. You just need to deal with this buffer and free will be OK. Because the data is read from buffer, the data will be ready when your callback is called, so the programmer doesn’t have to worry about blocking.

The writing is even more subtle. Libuv does not have a write callback. If you want to write something, generate a write Request and throw it to Libuv. Libuv adds your write requests to the corresponding socket’s write queue and writes them in order as I/O becomes writable.

C has no closures, so determining the read and write context is a problem for libuv users. Otherwise, the program will not be able to tell which data is which in the face of a flood of buffers. Libuv, like Libev, uses a void *data to solve the problem. You can use the data member to store anything, so that when the buffer comes in, you simply cast the data to the type you want.

Libev has no asynchronous DNS resolution, which has been widely complained about.

Libuv has asynchronous DNS resolution, and the resolution results are also notified to the program via callbacks.

Libev is completely single-threaded.

Libuv requires multithreaded library support because it maintains an internal thread pool to handle calls such as getAddrInfo (3) that cannot be handled asynchronously.

Libev seems to have been developed by the author alone, version management is still CVS, and the community involvement is obviously low.

The Libuv community is very active, with people making issues and contributing code almost every day.

Libev does not support IOCP, which can be cumbersome if you need to run programs under Win.

Libuv supports IOCP and has corresponding scripts to compile Windows libraries.

———————————————————————————–

Q: Have bloggers benchmarked for both? What is their previous performance comparison?

A: THERE was A simple HTTP Hello World Server written in libev and Libuv. I can’t remember the exact results but I can say the performance difference is within 5%.

Q: Libuv is a blocking IO implementation on Unix, right? Will the number of threads in the thread pool in Libuv increase? Will there be an upper limit? Is there a block situation if the upper limit is reached?

A: 1. Libuv in about five months ago has not been using libev completely, see commit665a316aa9d551ffdd00d1192d0c3d9c88d7e866; 2. The number of libuv thread pools on BSS is fixed at 4. See github.com/joyent/libu… ; 3. Libuv’s thread pool shares a work queue, so no blocks occur

 

Libevent: The best-known, most widely used, and long-established cross-platform event library; Libev: Simpler design and better performance than Libevent, but not good enough for Windows; Libuv: The process of node development requires a cross-platform event library, they preferred libev, but also to support Windows, so repackaged a set of * NIx using Libev, Windows using IOCP implementation;Copy the code