Epoll模型

C10K problem

C10K问题在1999年被提出,随着技术的发展,又出现了C100K,C10M等等相近的问题,不过问题本质相同。

这个问题的本质在于如何优化网络套接字,从而让服务器可同时处理大量的客户端请求。

并发连接和每秒请求数(QPS)不同。QPS可以通过提高处理速度(吞吐量)来提高。而并发连接数则要靠对于资源调度来实现。

1. 一对一

既每个请求使用一个线程。

这种处理方式主要有两个问题。
lea

内存

linux的thread stack size是8MB(ulimit -s),那么512个thread就可以撑爆一个32位主机的内存。这个问题在64位主机上的影响不大,但是处理10k请求就需要80GB内存,这还是有些可怕的。

上线文切换

排开内存问题外,更大的问题是上下文切换时带来的开销,这里我不太懂,可以参考这篇Article,讲的很详细。

2. 就绪通知机制。

也就是下面所说。

Diff

Select和Epoll在大体上相同,在有些小细节上有些不同。

功能上

先看一下 man select 的用法

int
select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds,
     struct timeval *restrict timeout);
  • Select 在使用时会覆盖readfds, writefdserrorfds。所以你在跑主循环的时候必须要备份这些变量,否则select就会占用这些字节。Poll不会改变输入的任何数据,所以同一组输入可以一直拿来用。
  • Poll默认情况下同时处理超过1024个fd,而且不需要任何work-around。而Select使用定长的bitmasks来存储文件信息,非常麻烦,需要在特定平台编译时指定FD_SETSIZE才行。
  • Poll相比Select添加了更多的容错机制。
  • 时间格式不同,无伤大雅。

速度上

两个速度基本相同,都很慢(大佬说的)。

  • 两者检查fd都是线性时间,fd越多检查越慢,最后等待fd事件和检查事件归属会占据很明显的时间,成为系统瓶颈。
  • Select提供了一个可选参数nfds,表明最多检查多少个FD,poll去掉了这个参数。
  • Select使用三个二进制位来表示一个fd,但是poll一般需要64个二进制位来表示。因此,每次系统调用poll都需要copy一大堆东西到kernel space。select在这方便略胜一筹。

Farther Reading

StackOverFlow

C10K Problem

poll vs select vs event-based

QiNiu