Libevent Analysis Notes (3) - Determining I/O Multiplexing Mechanism
Libevent’s original intention was to design a cross-platform lightweight I/O framework. Due to historical issues, the I/O multiplexing mechanisms across different platforms are difficult to unify. Therefore, the methods for handling cross-platform compatibility deserve special attention.
eventop is defined in the source code as follows:
|
|
As can be seen, libevent uses macros to find available multiplexing mechanisms at compile time.
The order here is also significant. According to the official documentation, the multiplexing mechanisms supported by libevent include /dev/poll , kqueue(2) , event ports , select(2), poll(2) and epoll(4) .
Through benchmark testing of various mechanisms, libevent developers have chosen the priority order of multiplexing mechanisms based on performance from high to low, as shown in the figure:
****
This also reveals the lack of uniformity in mechanisms across different platforms. Standard poll and select can hardly meet the needs of large-scale architectures. For specifics, refer to Dan Kegel’s “The C10K problem ” document.
Regarding the adoption of mechanisms, libevent uses function pointers.
__
|
|
Each eventop corresponds to an I/O multiplexing mechanism, where each function pointer points to methods for operating events using that mechanism.
For example, in the eventop structure corresponding to epoll:
- The void *(*init)(…) function pointer corresponds to static void * epoll_init(…)
- In epoll_init(), it first checks the environment variables and returns NULL immediately if epoll mechanism is not found.
- It uses epoll_create(32000) to specify an upper limit of 32000 connections, then allocates resources needed for each member of epollop.
- Finally, it calls libevent’s own signal initialization function.
The process of selecting and initializing a mechanism is very simple:
|
|

It traverses the eventops array storing mechanisms, trying to initialize them in order. Once a mechanism is successfully initialized, it immediately exits the loop. Of course, you don’t need to worry about all the trivial details of detecting available mechanisms in the system environment, choosing which mechanism is more suitable, or how to use specific multiplexing mechanisms. When using it, you just need to call the event_init() function. Libevent’s clever encapsulation of various multiplexing mechanisms saves developers from the trouble of dealing with mechanism selection when handling cross-platform issues in large-scale architectures.
Original link: http://www.cppblog.com/xguru/archive/2010/06/25/118722.html