Google大神 Jeff Dean在之前的一次演讲中展示了这样一张表,非常有意思:
从这张图里我们可以清楚的看到,计算机系统中各种关键操作其典型耗时到底有多少(注意,各种不同的系统架构精确的数据可能与此不同,但数量级上差别应该不会很大),注意,图中的数据取自2012年数据,最新版数据可以参考这里。
访问L2 cache的时延大概是访问L1 cache的10几倍左右,而访问一次内存的时延则高达访问L2 cache的20倍,是访问L1cache耗时的200倍。
这一部分清楚的告诉每个程序员,编写出对cache友好的程序是至关重要的,尤其你的场景如果对性能要求很高则更是如此。
分支预测失败的惩罚大概只有5ns这个量级,博主在之前的文章《特斯拉遇上CPU:程序员的心思你别猜》这篇文章中专门讲解过CPU的分支预测功能。
该功能主要针对 if 语句,由于现代CPU内部采用流水线方式来处理机器指令,因此在 if 对应的机器指令还没有执行完时后续指令就要进到流水线中,此时CPU就必须猜测到底 if 语句是否为真,如果CPU猜对了,那么流水线照常运行,但如果猜错了流水线中已经被执行的一部分指令就要作废。
很多同学看到这篇文章后表示if语句是不是尽量少用,从这张表可以看出,分支预测失败的惩罚不高,并且现代CPU的分支预测成功率很高,根本不必在意这点性能损失。
当然,如果你真的很在意性能的话那么算法也必不可少,这就是为什么大厂这么注重算法的原因,在这里我也送一本帮我拿到BAT等一线大厂offer的算法笔记,是一位阿里大神写的,对于算法薄弱或者需要提高的同学是真心有用,分享给大家,希望这份笔记也能帮到你:突击进大厂,阿里P8大佬写的Leetcode刷题笔记
程序员都知道访问内存的速度比SSD块,访问SSD速度比磁盘快,那么到底能快多少呢?同样顺序读取1MB数据,内存花费的时间为250,000 ns,SSD为1,000,000 ns,磁盘为20,000,000 ns。我们可以看到,同样读取1MB数据,磁盘花费的时间是 SSD 的 20 倍,是内存的80倍。
同样读取1MB数据,SSD耗时是内存的4倍。这组数据告诉我们,相对内存来说磁盘真的很慢,如果你的经费充足就用SSD吧,如果你是土豪,那么就把数据库直接放到内存吧。
一般来说我们认为内存比磁盘快,磁盘比网络快,但这这张表告诉我们用1Gbps网络发送1K数据仅仅需要20,000 ns,而磁盘的一次寻道则高达10,000,000ns(10ms),在特定场景下网络IO可不一定比磁盘IO慢。当然,这也要看网络两端距离有多远。
为了让大家能更加直观的感受速度差异,我们依然以第一张表为例,并且把计算机世界中的0.5纳秒当做1秒来换算一下,这样你就能清楚的感受到这些计算机世界中各个硬件巨大的速度差异了。我们再来看一下:
现在就很有意思了,假定L1 cache的访问延迟为1s,那么访问内存的延迟就高达3分钟。
从内存上读取1MB数据需要5天,从SSD上读取1MB需要20天,磁盘上读取1MB数据高达1年的时间。
更有趣的来了,假设物理机重启的时间为2分钟,如果也将0.5ns视为1s的话那么2分钟就相当于5600年,中华文明上下五千年,大概就是这样一个尺度。
现在你应该能直观的感受到CPU的速度到底有多快了吧。
以上都是基于时间维度换算的。接下来我们基于距离维度进行了一次更有意思的换算。
CPU访问L1 cache 的时延为0.5ns,假定在这个时间尺度下我们能行走1米,大概是你从在家里走两步拿个快递的距离。
CPU访问内存的时延里我们可以行走200米,大概是你出门去个便利店的距离。
CPU从内存中读取1MB的时延我们可以行走500公里,这个距离大概是从北京到青岛的直线距离。
网络包在数据中心内部走一圈的时延可以让我们行走1000公里,大概是从北京到上海的直线距离。
从SSD中读取1MB的时延可以让我们行走2000公里,大概是从北京到深圳的距离。
从磁盘中读取1MB的时延可以让我们行走40000公里,正好是围绕地球转一圈的距离。而网络数据包从美国加利福尼亚到荷兰转一圈的时延可以让我们行走30万公里,正好是从地球到月球的距离。
物理机一次重启的时延可以让我们行走1.2亿公里,差不多是从地球到火星的距离。
现在你应该对计算机系统中各种时延有一个直观上的认知了吧。
关于CPU更多内容你可以参考这篇:码农的荒岛求生:你管这破玩意叫 CPU ?
有很多同学问你能写出这些文章都读过哪些书,在这统一说下,计算机书籍浩如烟海,但贵精不贵多,我在这里精心挑选了10本 ,不要贪心,如果你真能把这里推荐的 10 本书读通,可以说你已经能超越 90% 的程序员并成为高手中的高手了。
最后,如果你对博主这种讲解风格感兴趣,那么我在知乎上写的很多这类文章你一定不能错过,有很多知乎朋友问有没有pdf版本,现在我也整理出来了,绘图非常精美,现在免费分享给大家。
作者:码农的荒岛求生
cache访问时间没有具体的指标,厂商不会公布这些,也许内部材料有,但对外肯定没有。厂商公布的只有指令性能:
但指令性能也很粗糙,比较难以统计,比如微指令不同的port占用会导致流水线性能的差异。
非官方的资料里,有一些人会测试:
这里的4个cycle是longest latency,理论上可能小于这个值。
还有一些更具体的数值:
题主的一些问题:
访问一次cache要多少时间?
对齐情况下,就是我前面的图,文章也提到了,在后来的Intel CPU里,latency更大(貌似是从4变到了5),因为cache变大了,但由于cache size更大,所以CPU性能有提升。
访问一次内存要多长时间?
这里还取决于内存控制器的情况,访问冲突延迟会更大,没有具体的指标,也取决硬件性能。内存频率会影响这个指标。
访问一次磁盘页面要多长时间?
纯粹的操作系统软件实现,取决于软件设计,也取决于硬件性能,SSD肯定比机械硬盘要快。
判断一次缓存行命中还是不命中需要多长时间?
如果是单独的hit test,在L1 cache这一块,不一定需要时间(取决于CPU设计,早年貌似没有),但load一定需要时间,对于L2,L3来说是需要时间的,具体指标没有,但我印象里是一个比较小的数值,L2/L3 load的过程,主要是因为加载慢,一次load一个cache line(64B)的时间比较多。
题外话:题主的理解里,取一个数据消耗4个cycle,取两个数据消耗8个,实际情况是,指令会预取,并且按流水线的方式工作,取一个是4个cycle,取两个可能是5个。要知道在指令性能的表格上,多条ADD指令按吞吐量计算,每个指令平均可能会小于一个cycle(按平均吞吐量计算,不代表单个指令的执行时间)。