Why Nginx performance is much higher than Apache _ server other

Source: Internet
Author: User
Tags epoll int size socket

Why is the performance of nginx much higher than Apache? This is thanks to the Nginx's use of the latest epoll (Linux 2.6 kernel) and Kqueue (FreeBSD) network I/O models, while Apache uses the traditional select model.

At present, the Epoll network I/O model is adopted in the squid and memcached which can withstand high concurrent access under Linux.

The Select Network I/O model used by Apache is very inefficient when handling a large number of connected reads and writes.

Here's a metaphor to parse the difference between the Select model that Apache uses and the Epoll model that Nginx uses:

Suppose you are studying in a university, there are many rooms in the dormitory building, your friend will come to see you.

The select version of the aunt will take your friend to the room to find you until she finds you.

And the Epoll version of the aunt will first write down the room number of each classmate,

When your friends come, just tell your friends which room you live in, and don't have to bring your friends over to the building to find someone.

If come 10,000 people, all want to find oneself live this building classmate, select version and Epoll version of Aunt, who is more efficient, self-evident.

Similarly, polling I/O is one of the most time-consuming operations in a high concurrency server, and the performance of select and Epoll is equally clear.

Copy Code code as follows:

EPOLL-I/O Event Notification Facility

In Linux network programming, it is a long time to use Select to do event triggering.

In the new Linux kernel, there is a mechanism to replace it, which is epoll.

The biggest advantage over Select,epoll is that it does not reduce efficiency as the number of listening FD increases.

Because in the select implementation in the kernel, it is handled by polling, the more the number of polled FD, the more natural time consuming.

Also, the LINUX/POSIX_TYPES.H header file has such a statement:

#define __FD_SETSIZE 1024

Indicates that the select has up to 1024 FD at the same time, of course, you can enlarge the number by modifying the header file and then recompiling the kernel, but this does not seem to be a permanent fix.

The Epoll interface is very simple, with a total of three functions:

1. int epoll_create (int size);

Creates a epoll handle, which is used to tell the kernel how large the number of listeners is.

This parameter differs from the first parameter in select () and gives the value of the maximum listener fd+1.

Note that when you create a good epoll handle, it takes up an FD value, and if you look at the/proc/process id/fd/under Linux,

is able to see this fd, so after using Epoll, you must call Close (), or it may cause the FD to run out.

2. int epoll_ctl (int epfd, int op, int fd, struct epoll_event *event);

Epoll Event Registration function, which differs from select () to tell the kernel what type of event to listen to when listening for an event,

Instead, you register the type of event you want to listen to first. The first parameter is the return value of Epoll_create (),

The second parameter represents the action, represented by three macros:

Epoll_ctl_add: Register the new FD to EPFD;

Epoll_ctl_mod: Modify the Listening event of the registered FD;

Epoll_ctl_del: Deletes an FD from the EPFD;

The third parameter is the FD that needs to be monitored, and the fourth parameter tells the kernel what to listen to, and the struct epoll_event structure is as follows:

Copy Code code as follows:

typedef Union EPOLL_DATA {
void *ptr;
int FD;
__uint32_t u32;
__uint64_t U64;
} epoll_data_t;
struct Epoll_event {
__uint32_t events; * Epoll Events * *
epoll_data_t data; /* USER Data variable * *
};

Events can be a collection of several macros:
Epollin: Indicates that the corresponding file descriptor can be read (including closing the socket properly);
Epollout: Indicates that the corresponding file descriptor can be written;
Epollpri: Indicates that the corresponding file descriptor has an urgent data readable (here should indicate the arrival of Out-of-band data);
Epollerr: Indicates that the corresponding file descriptor has an error;
Epollhup: Indicates that the corresponding file descriptor is hung;
Epollet: Sets the Epoll as the Edge trigger (edge triggered) mode, which is relative to the level triggered.
Epolloneshot: Only one event is monitored, and after this event is monitored,
If you still need to continue listening to this socket, you need to add this socket to the Epoll queue again.

3. int epoll_wait (int epfd, struct epoll_event * events, int maxevents, int timeout);

Wait for the event to occur, similar to the Select () call.
Parameter events are used to get the collection of events from the kernel, maxevents the kernel of this event, the Maxevents value cannot be greater than the size when the Epoll_create () is created, and the parameter timeout is the timeout (milliseconds, 0 will return immediately ,-1 will be uncertain, and there are claims that it is permanently blocked.
The function returns the number of events that need to be handled, such as returning 0 to indicate that the timeout has expired.

4, about ET, lt two kinds of working mode:

The

can conclude that the
et mode is only notified when the state changes, and that the state changes here do not include data that is not processed in the buffer, that is, if you want to use the ET mode, you need to keep read/write until an error occurs. Many people reflect why the use of ET mode only received a part of the data will no longer be notified, mostly because of this, and the LT mode is as long as there is no data processing will always be informed.

So how exactly do you use Epoll? actually very simple. The
by including a header file #include <sys/epoll.h> and a few simple APIs will greatly increase the number of support for your network server. The
first creates a epoll handle by create_epoll (int Maxfds), where Maxfds is the maximum number of handles supported by you epoll.
This function will return a new epoll handle, and all subsequent operations will be manipulated through this handle.
When you are finished, use close () to turn off the created Epoll handle.
after the main loop in your network, each frame of the call epoll_wait (int epfd, epoll_event events, int max events, int timeout) to query all network interfaces, see which one can read, which one can write. The basic syntax is:
Nfds = epoll_wait (KDPFD, events, maxevents,-1);
where KDPFD is the handle created with Epoll_create, events is a epoll_event* Pointer, when epoll_wait This function succeeds, the epoll_events will store all the read and write events. The
Max_events is the number of all socket handles that are currently listening. The last timeout is the epoll_wait timeout, which means that when 0 is returned immediately, the 1 indicates that it has been waiting until there is an event range, for any positive integer to represent such a long time, if there has been no event, then the scope. Generally if the network main loop is a separate thread, you can use-one, etc., so as to ensure some efficiency, if it is the same thread with the main logic, you can use 0来 to ensure the efficiency of the main cycle. The

Epoll_wait range should be followed by a loop that benefits all events.
Almost all Epoll programs use the following framework:

for (;;)
  {Nfds = epoll_wait (epfd,events,20,500); for (I=0;i<nfds;++i) {if (EVENTS[I].DATA.FD==LISTENFD)//has a new connection {CONNFD = Accept (LISTENFD, (SOCKADDR *) &c LIENTADDR, &clilen);
    Accept this connection ev.data.fd=connfd; ev.events=epollin|
    Epollet; Epoll_ctl (Epfd,epoll_ctl_add,connfd,&ev); Add new FD to Epoll's listening queue} else if (Events[i].events&epollin)/Receive data, read socket {n = read (SOCKFD, line, MAXL  INE) < 0//Read EV.DATA.PTR = MD; MD for custom type, add Data ev.events=epollout|
    Epollet; Epoll_ctl (Epfd,epoll_ctl_mod,sockfd,&ev);//modify identifiers, wait for the next loop to send data, the essence of the asynchronous process} else if (events[i].events&epollout
    //have data to send, write socket {struct myepoll_data* MD = (myepoll_data*) events[i].data.ptr;//Fetch data SOCKFD = md->fd;  Send (SOCKFD, Md->ptr, strlen ((char*) md->ptr), 0);
    Send data ev.data.fd=sockfd; ev.events=epollin|
    Epollet; Epoll_ctl (Epfd,epoll_ctl_mod,sockfd,&ev);
 Modify identifiers, wait for Next loop to receive data} else {//other processing  }
  }
 } 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.