Difference between select and epoll models

1. Difference between select and epoll models

1.1. Overview of network IO model

     Generally speaking, network IO can be abstracted into data exchange between user mode and kernel mode. A network data read operation (read) can be divided into two steps: 1) The network card driver waits for the data to be ready (kernel mode) 2) Copy the data from the kernel space to the process space (user mode). According to the different processing methods of these two steps, we usually divide network IO into blocking IO and non-blocking IO.

      · Blocking IO. When the user calls a system call related to network IO (such as read), if the kernel network card has not read the network data at this time, the system call will be blocked until the data sent by the peer system arrives. If the peer has not sent data, this call will never return.

      · Non-blocking IO. When the user calls a system call related to network IO (such as read), if the kernel network has not received network data at this time, the system call will return immediately and an error code of EAGAIN will be returned.

Before there is no IO multiplexing technology, there is no good way to detect whether the network IO is readable and writable. Therefore, in order to increase the number of concurrent connections of the system, the number of concurrent connections of the system is generally increased by means of multi-threading or multi-process. However, there is a problem with this method that the number of concurrent connections of the system is limited by the maximum number of threads or processes of the operating system, and as the number of threads or processes of the operating system increases, a large number of context switches will be triggered, resulting in sharp system performance. decline. In order to solve this problem, the operating system introduced IO multiplexing technology (IO multiplexing).

1.2. IO multiplexing technology

    IO multiplexing technology is actually a mechanism for detecting IO events using system calls provided by operating systems such as select and epoll. Through mechanisms such as select and epoll, we can easily manage a large number of network IO connections at the same time, and obtain active connections. When one or more of the network IO events occur, system calls such as select and epoll will return the corresponding connections, and we can read or write these connections to complete network data interaction.

1.3. How select works

       select function prototype:

        int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

          Select each parameter description:

               ·  nfds

The value of this parameter is generally set to the largest descriptor (fd) + 1 in the read set (readfds), write set (writefds) and exceptfds (exception set), of course, it can also be set to FD_SETSIZE. FD_SETSIZE is a macro defined by the operating system, usually 1024. That is to say, the maximum value of read and write and exception set size is 1024, so using select can only manage up to 1024 connections. If there are more than 1024 connections, select will have undefined behavior.

· readfds

A pointer to the readable descriptor set. If we care about the readable events of the connection, we need to set the descriptor of the connection into the read set.

·writefds

A pointer to the writable descriptor set. If we care about the writable events of the connection, we need to set the connection's descriptor to the writable set.

· exceptfds

A pointer to the exception descriptor set. If we care about whether an exception occurs in the connection, we need to set the connection descriptor to the exception descriptor set.

·timeout

Refers to the time that select is willing to wait.

                      struct timeval {

                                           longtv_sec; //seconds

                                           longtv_usec; ​​// microseconds

                                   }

                Generally speaking, there are three cases:

·timeout is empty, select will wait forever. Returns until a connection is readable, writable, or interrupted by a signal.

·timeout->tv_sec = 0 and timeout->tv_usec = 0, do not wait at all. Returns as soon as all specified descriptors have been detected. This is the polling method to get the status of multiple descriptors without blocking the select function.

·timeout->tv_sec != and timeout->tv_usec != 0, wait for the specified number of seconds and microseconds. Returns immediately when one of the specified descriptors is ready, or exceeds the specified time value. If the timeout expires and no descriptor is ready, 0 is returned.

     The working principle of select, select detects the state of the descriptor (fd) in each set by polling. If the state of the descriptor changes, the corresponding flag bit will be set in the set; if the state of the specified descriptor does not If a change occurs, the descriptor is removed from the corresponding set. Therefore, the call complexity of select is linear, that is, O(n). For example, a nanny takes care of a group of children. If you compare whether the child needs to pee to a network IO event, the role of select is like the nanny asking each child one by one: Do you want to pee? If the child answers yes, the babysitter will take the child out and put it in another place. After all the children have been questioned, the nanny takes the children who need to pee to the toilet (to handle network IO events).

    The limit of select, mentioned earlier, the FD_SETSIZE macro, this macro is defined by the operating system. Under Linux, it is usually 1024, which means that select can only manage up to 1024 descriptors. If there are more than 1024 descriptions, select will have unpredictable behavior. In the absence of poll or epoll, how to use select to handle the case where the number of connections is greater than 1024? The answer is to use multi-threading techniques, each thread uses a separate select for detection. In this case, the number of concurrent connections your system can handle is equal to the number of threads * 1024. Early apache is this technology to support massive connections.

1.4. How epoll works

  epoll function prototype:

        int epoll_create(int size);

        intepoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

 

                int epoll_wait(intepfd,  struct epoll_event *events, intmaxevents,  int timeout);

         Relying on the above three functions, epoll can manage thousands of concurrent connections. How to use epoll, 1) Create an epoll handle through epoll_create. 2) The events of interest to the descriptor are added to the epoll handle via epoll_ctl. 3) Call epoll_wait to return all readable and writable descriptors.

  epoll is an improved epoll of the Linux kernel for processing large batches of file descriptors . It is an enhanced version of the multiplexed IO interface select/poll under Linux. It can significantly improve the program in the case of a large number of concurrent connections with only a small amount of activity. system CPU utilization. Another reason is that when acquiring an event, it does not need to traverse the entire listening descriptor set, but only needs to traverse the descriptor sets that are asynchronously awakened by the kernel IO event and added to the Ready queue. In addition to providing Level Triggered for IO events such as select/poll, epoll also provides Edge Triggered, which makes it possible for user-space programs to cache IO status, reduce epoll_wait/epoll_pwait calls, and improve application performance. program efficiency.

      Take the nanny taking care of a group of children as an example. Under the epoll mechanism, the nanny no longer needs to ask each child one by one whether they need to pee. Instead, if each child needs to pee, he will take the initiative to stand in the pre-agreed place, and the duty of the nanny is to check whether there is a child in the pre-agreed place. If there is a child, take the child to the toilet (network incident handling). Therefore, this mechanism of epoll can efficiently handle thousands of concurrent connections, and the performance will not decrease as the number of connections increases.

1.5. Comparison between select and epoll

In summary, the comparison between select and epoll is shown in the following table

 

select

epoll

performance

It drops sharply as the number of connections increases. Poor performance when dealing with thousands of concurrent connections.

There is essentially no degradation in performance as the number of connections increases. Performance is good when handling thousands of concurrent connections.

number of connections

The number of connections is limited, and the maximum number of connections handled does not exceed 1024. If you want to handle more than 1024 connections, you need to modify the FD_SETSIZE macro and recompile.

Unlimited number of connections.

internal processing mechanism

Linear polling

callback callback

development complexity

Low

middle

 

The simple difference between select and epoll analogy

The call complexity of select is linear, ie O(n). For example, a nanny takes care of a group of children. If you compare whether the child needs to pee to a network IO event, the role of select is like the nanny asking each child one by one: Do you want to pee? If the child answers yes, the babysitter will take the child out and put it in another place. After all the children have been questioned, the nanny takes the children who need to pee to the toilet (to handle network IO events).

Take the nanny taking care of a group of children as an example. Under the epoll mechanism, the nanny no longer needs to ask each child one by one whether they need to pee. Instead, if each child needs to pee, he will take the initiative to stand in the pre-agreed place, and the duty of the nanny is to check whether there is a child in the pre-agreed place. If there is a child, take the child to the toilet (network incident handling). Therefore, this mechanism of epoll can efficiently handle thousands of concurrent connections, and the performance will not decrease as the number of connections increases.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325825414&siteId=291194637