C10K problem
C10K问题在1999年被提出,随着技术的发展,又出现了C100K,C10M等等相近的问题,不过问题本质相同。
这个问题的本质在于如何优化网络套接字,从而让服务器可同时处理大量的客户端请求。
并发连接和每秒请求数(QPS)不同。QPS可以通过提高处理速度(吞吐量)来提高。而并发连接数则要靠对于资源调度来实现。
Popular solution
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
,writefds
和errorfds
。所以你在跑主循环的时候必须要备份这些变量,否则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在这方便略胜一筹。