请教大家一个问题,下图这个最简单的例子会造成怎样的CPU开销?你能说清楚吗?get('test');...这个例子结合了你在我的文章中学到的知识和你的实际工作。怎么样,够简单了吧?它只是一段php代码,用于从redis实例中获取键的值。我相信你每天都在写类似的代码。对这个redisget的实际成本的理解程度代表了你内功的深浅。上一篇介绍了一些CPU相关的硬件和内核知识,具体分析了进程上下文切换、系统调用、软中断这些开销比较大的开销。还没有看过的同学请注意看我之前的文章。但是,这个时候,我想很多开发同学都有一个疑惑,他们还是会想:“我是应用层的开发人员,底层的开销和我有什么关系呢?”或者说:“线上服务器的运维不应该都是运维工作吗?跟开发没有关系。”我想说的是,如果你只是一个初中级开发工程师,真的没有必要去了解这些。但是如果你想做高级或者高级开发工程师,那么你就应该有能力粗略估算你写的每一行代码的成本,并且对你的代码在线运行成本负责!接下来,就带大家从更深的层次来理解这段简单代码的开销。为了方便测试,我们对代码进行了一些简单的修改,最终实际测试代码如下:connect({Redis服务器IP},6339);睡觉(60);echo"测试开始\n";for($i=0;$i<10000;$i++){$redis->get('测试');}echo"测试结束!\n";睡觉(60);例子很简单,就是后端同学代码中经常出现的一段从Redis中获取的数据。那么让我们看看它会产生什么开销?1.系统调用#strace-cphpmain.php%timesecondsusecs/callcallserrorssyscall---------------------------------------------------------97.240.039698130003轮询2.200.000899010003发送到0.300.000122010000recvfrom0.130.000053010069gettimeofday0.030.00001326socket0.030.0000120408munmap0.020.0000080657read我们代码调用的get函数其实是由php的redis扩展提供的。扩展会调用Linux系统的网络库函数,库函数会调用内核提供的系统调用。调用层次模型如下:从实际测试结果可以看出,每个get操作需要执行多次系统调用才能完成。2.进程上下文切换每次调用get后,如果没有返回数据。进程被阻塞,所以也会导致进程进入主动上下文切换。我们以实验的方式查看一下:#phpmain.php然后再启动一个控制台,实验前后分别执行如下两行命令:#grepctxt/proc/14862/statusvoluntary_ctxt_switches:4nonvoluntary_ctxt_switches:43#grepctxt/proc/14862/statusvoluntary_ctxt_switches:10005nonvoluntary_ctxt_switches:49每次get都会导致进程进入自愿上下文切换。在网络IO密集型应用中,自愿的上下文切换比时间片到来时的被动切换要多。许多!3、软中断每次redis服务器返回数据时,网卡都会通过软中断让内核处理数据包。因此#cat/proc/softirqsCPU0CPU1CPU2CPU3HI:0000TIMER:196173081145428444154228333163317242NET_TX:0000NET_RX:17815992811607310108160712#cat/proc/softirqsCPU0CPU1CPU2CPU3HI:0000计时器:196173688145428634154228610163317624net_tx:00000net_rx:17817021211607310108160712虚拟机的软中断亲和力在CPU0,1781702121212-178178.98.944.94.94.99.99.99.99.99.98.98.98.98.98(28)get请求接收数据并返回,内核必须付出软中断的开销!总结看来一个很简单的redisget操作会涉及系统状态的所有高开销操作。一个进程上下文切换,一个软中断,以及几个系统调用,经过之前的很多文章,相信大家对自己的开销有了一个量化的把握。事实上,除了上述易于评估的开销外,还有L1、L2缓存未命中和TLB缓存未命中会导致缓存命中率下降和进程关闭时的额外开销。所以,你认为简单的不一定简单!练内功专用CPU:1、你以为你的多核CPU是真核生物吗?多核“错觉”2、听说你只知道内存,不知道缓存?CPU表示很伤心!3.TLB缓存是个鬼,如何查看TLBmiss?4、进程/线程切换需要多少开销?5、协程比线程好在哪里?6.softirq会吃掉多少CPU?7、一次系统调用的开销是多少?8、一个简单的php请求redis的开销是多少?9、函数调用过多会不会有性能问题?我的公众号是“练内功练功”。在这里,我不是简单地介绍技术理论,也不是只介绍实践经验。而是理论联系实际,用实践加深对理论的理解,用理论提高技术实践能力。欢迎关注我的公众号,分享给你的朋友吧~~~
