CPU的时间观

本文通过将CPU的速度与人类感知的时间进行对比,揭示了计算机各组件间的速度差异。CPU每秒可执行数十亿指令,而磁盘和网络速度则显得极其缓慢。缓存、分支预测、内存寻址、上下文切换等操作在CPU眼中都需要“漫长”的时间。理解这些差距对于性能优化至关重要。
摘要由CSDN通过智能技术生成

简介

    经常听到有人说磁盘很慢、网络很卡,这都是站在人类的感知维度去表述的,比如拷贝一个文件到硬盘需要几分钟到几十分钟,够我去吃个饭啦;而从网络下载一部电影,有时候需要几个小时,我都可以睡一觉了。

    最为我们熟知的关于计算机不同组件速度差异的图表,是下面这种金字塔形式:越往上速度越快,容量越小,而价格越高。这张图只是给了我们一个直观地感觉,并没有对各个速度和性能做出量化的说明和解释。而实际上,不同层级之间的差异要比这张图大的多。这篇文章就让你站在 CPU 的角度看这个世界,说说到底它们有多慢。

    希望你看到看完这篇文章能明白两件事情:磁盘和网络真的很慢,性能优化是个复杂的系统性的活。

CPU速度

目前电脑主频是2.6G,也就是说每秒可以执行 2.6*10^9 个指令,每个指令只需要 0.38ns(现在很多个人计算机的主频要比这个高,配置比较高的能达到 3.0G+

我们假设一个指令时间比作人类能够感知的一秒钟来对比数据

一级缓存

一级缓存读取时间为 0.5ns,换算成人类时间大约是 1.3s,大约一次或者两次心跳的时间。

这里能看出缓存的重要性,因为它的速度可以赶上 CPU,程序本身的 locality 特性加上指令层级上的优化,cache 访问的命中率很高,这最终能极大提高效率。

分支预测

分支预测错误需要耗时 5ns,换算成人类时间大约是 13s,相当于成年男子100米奔跑

指令形成流水线以后,就需要一种高效的调控来保证硬件层面并发的效果:最佳情况是每条流水线里的十几个指令都是正确的,这样完全不浪费时钟周期。而分支预测就是干这个的

分支预测器猜测条件表达式两路分支中哪一路最可能发生,然后推测执行这一路的指令,来避免流水线停顿造成的时间浪费。但是,如果后来发现分支预测错误,那么流水线中推测执行的那些中间结果全部放弃,重新获取正确的分支路线上的指令开始执行,这就带来了十几个时钟周期的延迟,这个时候,这个 CPU 核心就是完全在浪费时间。

幸运的是,当下的主流 CPU 在现代编译器的配合下,把这项工作做得越来越好了。

还记得那个让 Intel CPU 性能跌 30% 的漏洞补丁吗,那个漏洞就是 CPU 设计的时候,分支预测设计的不完善导致的。

参考链接:Why is processing a sorted array faster than processing an unsorted array?

二级缓存

二级缓存时间大约在 7ns,换算成人类时间大约是 18.2s,相当于成年男100米跨栏。

如果一级缓存没有命中,然后去二级缓存读取数据,时间差了一个数量级。

tips:为什么需要多层CPU缓存

互斥锁的加锁和解锁

互斥锁的加锁和解锁时间需要 25ns,换算成人类时间大约是 65s,首次达到了一分钟。

并发编程中,我们经常听说锁是一个很耗时的东西,因为在微波炉里加热一个东西需要一分钟的话,你要在那傻傻地等蛮久了。

内存

每次内存寻址需要 100ns,换算成人类时间是 260s,也就是4分多钟,相当于阅读一个章节的网络小说。

看起来还不算坏,不过要从内存中读取一段数据需要的时间会更多。到了内存之后,时间就变了一个量级,CPU 和内存之间的速度瓶颈被称为冯诺依曼瓶颈。

究竟什么是冯诺依曼瓶颈(von Neumann Bottleneck)?

性能之殇:从冯·诺依曼瓶颈谈起

CPU 上下文切换

一次 CPU 上下文切换(系统调用)需要大约 1500ns,也就是 1.5us(这个数字参考了这篇文章,采用的是单核 CPU 线程平均时间),换算成人类时间大约是 65分钟,嗯,也就是一个小时。

我们也知道上下文切换是很耗时的行为,毕竟每次浪费一个小时,也很让人有罪恶感的。上下文切换更恐怖的事情在于,这段时间里 CPU 没有做任何有用的计算,只是切换了两个不同进程的寄存器和内存状态;而且这个过程还破坏了缓存,让后续的计算更加耗时。

在 1Gbps 的网络上传输 2K 的数据

需要 20us,换算成人类时间是 14.4小时,这么久都能把《星球大战》六部曲看完了!

可以看到网络上非常少数据传输对于 CPU 来说,已经很漫长。而且这里的时间还是理论最大值,实际过程还要更慢一些。

SSD 随机读取

耗时为 150us,换算成人类时间大约是 4.5天。换句话说,SSD 读点数据,CPU 都能休假,报团参加周边游了。

虽然我们知道 SSD 要比机械硬盘快很多,但是这个速度对于 CPU 来说也是像乌龟一样。I/O 设备 从硬盘开始速度开始变得漫长,这个时候我们就想起内存的好处了。尽量减少 IO 设备的读写,把最常用的数据放到内存中作为缓存是所有程序的通识。像 memcached 和 redis 这样的高速缓存系统近几年的异军突起,就是解决了这里的问题。

从内存中读取 1MB 的连续数据

耗时大约为 250us,换算成人类时间是 7.5天,这次假期升级到国庆七天国外游。

同一个数据中心网络上跑一个来回

需要 0.5ms,换算成人类时间大约是 15天,也就是半个月的时间。

如果你的程序有段代码需要和数据中心的其他服务器交互,在这段时间里 CPU 都已经狂做了半个月的运算。减少不同服务组件的网络请求,是性能优化的一大课题。

从 SSD 读取 1MB 的顺序数据

大约需要 1ms,换算成人类时间是 1个月

也就是说 SSD 读一个普通的文件,如果要等你做完,CPU 一个月时间就荒废了。尽管如此,SSD 已经很快啦,不信你看下面机械磁盘的表现。

磁盘寻址时间

10ms,换算成人类时间是 10个月,刚好够人类创造一个新的生命了。

如果 CPU 需要让磁盘泡杯咖啡,在它眼里,磁盘去生了个孩子,回来告诉它你让我泡的咖啡好了。机械硬盘使用 RPM(Revolutions Per Minute/每分钟转速) 来评估磁盘的性能:RPM 越大,平均寻址时间更短,磁盘性能越好。寻址只是把磁头移动到正确的磁道上,然后才能读取指定扇区的内容。换句话说,寻址虽然很浪费时间,但其实它并没有办任何的正事(读取磁盘内容)。

从磁盘读取 1MB 连续数据

20ms,换算成人类时间是 20个月

IO 设备是计算机系统的瓶颈,希望读到这里你能更深切地理解这句话!如果还不理解,不妨想想你在网上买的东西,快递送了将近两年,你的心情是怎么样的。

从世界上不同城市网络上走一个来回

平均需要 150ms(参考世界各地 ping 报文的时间),换算成人类时间是 12.5年

不难理解,所有的程序和架构都会尽量避免不同城市甚至是跨国家的网络访问,CDN就是这个问题的一个解决方案:让用户和最接近自己的服务器交互,从而减少网络上报文的传输时间。

虚拟机重启一次

大约要 4s 时间,换算成人类的时间是 3百多年

对于此,我想到了乔布斯要死命优化 Mac 系统开机启动时间的故事。如果机器能少重启而且每次启动能快一点,不仅能救人命,也能救 CPU 的命。

物理服务器重启一次

需要 5min,换算成人类时间是 2万5千年,快赶上人类的文明史了。

5 分钟人类都要等一会了,更别提 CPU 了,所以没事不要乱重启服务器啊,分分钟终结一个文明的节奏。

参考资料

What Every Programmer Should Know About Memory

Getting Physical With Memory

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值