分类: C/C++
2014-09-29 17:52:43
原文地址:并行服务器真的比串行快吗? 作者:尘世间一迷途小码农
曾经带过一个实习生,对我说“做服务器,并行肯定比串行快,因为并行可以开100个线程一起跑,当然比串行单个线程跑要快了”
答:“线程又不是凭空就能跑得起来的,要有CPU才能让线程跑起来。串行开辟CPU个数进程,还能避免锁和线程切换的开销,不是更快吗”
又问:“那为什么大家都说并行服务器比串行服务器快呢”
是啊,为什么呢?
首先我们要明确一点:服务器性能是从哪里来的。
软件本身是不能创造性能的,只有硬件烧掉电能之后才能获得性能(运算能力)。也就是说,无论并行模式还是串行模式,最佳的结果就是让所有CPU满负荷运转。
并行模式的服务器能保证所有CPU满负荷运转,达到最佳性能。
而串行模式往往会睡眠,睡眠其实就是线程需要等待某个资源,无法继续运行。服务器睡眠就会导致CPU闲着没事干,性能大幅下降。
什么情况下我们的服务器会睡眠,导致CPU没事干呢?
最常见的原因是读socket时,需要等待对方处理数据和网络传输。
串行模式下会直接睡眠,而在并行模式下,我们会用epoll+非阻塞模式socket来避免等待。
并行模式通过采用epoll+非阻塞/异步io,完全解决了睡眠问题。但是并行模式也引入了各种问题:例如程序逻辑会变得复杂,例如各个地方需要加锁。
就我的开发经验来看,同一个功能采用并行模式来实现要比采用串行模式增加30%的编码时间,对于质量要求高的行业(如电商、通信),采用并行模式还要面对极其难解决的同步bug。
备注:顺带提一句,我面试过的工程师中,只有不到0.1%的人知道并发环境下内存屏障的正确用法。
有没有什么办法,既能采用串行模式开发提高开发效率,又能让CPU达到满负荷运转呢?
如果我们能保证睡眠时间占总时间比例小于x,只要启动cpu_num * 1 / x个进程或线程,就可以保证每个CPU满负荷运转
假设我能控制线程处理每个请求是10ms逻辑运算时间+90ms睡眠时间,那么只要开CPU个数*10的进程,就可以保证每个CPU都跑满,达到最佳性能。
服务器和客户端之间的socket可能长时间等待,其睡眠时间是不可控的。但是通过nginx+fastcgi的模式,我们可以让nginx负责和客户端之间的连接,当收到完整的请求数据时再把请求转给我们的fastcgi,这样就完全避免了服务器和客户端之间socket通信带来的睡眠
剩下需要估算的延时就只有fastcgi和数据库之间的访问延时,这是一个可以控制的睡眠时间。
曾经做过的一款日活跃上亿的游戏就是采用这样的串行架构实现的。性能和并行一样都达到了最佳(能让所有CPU满负荷运转),同时又免去了加锁处理同步问题的麻烦。