# The reason why Nginx is faster than Apache http server and Redis is fast only using single-thread
---
# The C10K problem
http://www.kegel.com/c10k.html
---
# File descriptor

One basic concept of Linux (actually Unix) is the rule that everything in Unix/Linux is a file. Each process has a table of file descriptors that point to files, sockets, devices and other operating system objects.
---
# Network I/O model

- Signal I/O
----
## Blocking I/O

While a request comes, the application(user space) will ask kernel that data is ready or not and it will block until kernel responds.
----
## non-Blocking I/O

It just like polling.
----
## I/O multiplexing

----

----
### select

`int select(int maxfd,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout){}`
https://man7.org/linux/man-pages/man2/select.2.html
----
```
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Data is available now.\n");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.\n");
exit(EXIT_SUCCESS);
}
```
----
### cons of select
1. It polls all the fds to find which changed (O(n))
2. It only allows to monitor 1024 fds in a thread.
3. Need to copy fd from user space to kernel space.
----
### poll
`poll` is just like `select` but it fixes the second problem of `select`
`int poll(struct pollfd *fds, nfds_t nfds, int timeout);`
https://man7.org/linux/man-pages/man2/poll.2.html
----
### epoll, kqueue
You can take `epoll` as event sourcing.
`select` and `poll` only provide a API to use it.
But `epoll` provides 3 Apis.
1. `int epoll_create(int size);`
2. `int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);`
3. `int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);`
https://man7.org/linux/man-pages/man7/epoll.7.html
----
### How does epoll solve problems?
1. `epoll` only listens to the ready list to know which fd is ready so it solve the first problem of `select`.
2. `epoll` can watch more than 1024 fds.
3. `epoll` use mmap to share memory between kernel space and user space to solve the third problem of `select`.
----
### Benchmark

----
## Signal I/O

----
## Asynchronous I/O

---
# Why redis is fast
We all know that Redis is a single-thread service, and it is very fast.
Not only because it operates in memory but also it uses I/O multiplexing to handle the connections.
And redis uses reactor pattern to deal with multiple connections.
----

----
## Redis server.c

https://www.modb.pro/db/232774
https://juejin.cn/post/6844904160710623246
---
## Why nginx is better than Apache http server while the amount of connections is large.
Nginx uses I/O multiplexing as its network model furthur more it prefers to use epoll if the OS support it.
But Apache httpd (before 2.4) uses Blocking I/O model for both worker and prefork mode.
- Prefork mode: Process mode. Each request is handled by a child process. Thread safety. Not suitable for high-concurrency servers.
- Worker mode: Process thread mixed mode. The parent process will create child processes, and each child process will create multiple worker threads and a listener thread. Each thread is responsible for processing an http request.
Fortunatly, Aapche httpd 2.4 supports event mode and it bases on I/O multiplexing like Nginx.
https://httpd.apache.org/docs/2.4/mpm.html#defaults
----
## How a normal web server works

https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/
----
## How nginx works

https://www.aosabook.org/en/nginx.html
----
## Blocking is the big enermy to NGINX
https://www.nginx.com/blog/thread-pools-boost-performance-9x/
---
## Furthur more
https://hackmd.io/@sysprog/fast-web-server
https://hackmd.io/@jT29vQ4-SxmlBU5UMj1TGA/High_Performance_Web_Server
https://people.eecs.berkeley.edu/~culler/papers/events.pdf
https://copyconstruct.medium.com/the-method-to-epolls-madness-d9d2d6378642
---
# References
https://www.51cto.com/article/697808.html
https://devarea.com/linux-io-multiplexing-select-vs-poll-vs-epoll/#.Yv3el-xBxb8
https://developpaper.com/why-can-redis-single-thread-achieve-high-performance-and-io-multiplexing/
https://redis.com/blog/multiplexing-explained/
https://blog.51cto.com/u_11956937/2097035
https://notes.shichao.io/unp/ch6/
https://cloud.tencent.com/developer/article/1420724
----
https://programmer.group/analysis-of-io-multiplexing-and-event-mechanism-in-redis.html
https://www.youtube.com/watch?v=E7Yn5biBZ58
https://www.computerhope.com/jargon/f/file-descriptor.htm
https://rickhw.github.io/2019/02/27/ComputerScience/IO-Models/
https://www.modb.pro/db/232774
https://juejin.cn/post/6844904160710623246
https://blog.fearcat.in/a?ID=00001-ad1d6a96-fa83-4aa9-b9c3-468f79a8ba12
https://httpd.apache.org/docs/2.4/mpm.html#defaults
https://www.nginx.com/blog/thread-pools-boost-performance-9x/
https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/
---
### Thank you! :sheep:
<style>
.reveal {
font-size: 24px;
}
</style>
{"metaMigratedAt":"2023-06-17T07:06:20.074Z","metaMigratedFrom":"YAML","title":"The reason why Nginx is faster than Apache http server and Redis is fast only using single-thread","breaks":true,"description":"Just simple memo for network I/O","slideOptions":"{\"theme\":\"solarized\"}","contributors":"[{\"id\":\"661583cb-db49-43b5-b24d-5ae18d46764b\",\"add\":7552,\"del\":1061}]"}