性能优化系列:每个程序员都应该知道的数字(1)

这些数字与我们后续做性能优化息息相关,因此我将这部分内容放在第一篇,帮助大家建立基本的性能概念。

先来看 Jeff Dean 所说的数字是哪些:

注:1μs = 1000ns、1ms = 1000μs

操作

耗时/延迟

耗时*10亿

一级缓存读取(L1)

0.5ns

0.5s

分支错误预测

5ns

5s

二级缓存读取(L2)

7ns

7s

互斥锁的加锁解锁

25ns

25s

内存寻址

100ns

100s

Zippy压缩1KB数据

3000ns(3μs)50min

在1Gbps网络上发送1KB数据

10,000ns(10μs)

2.8h

从SSD(1GB/s)随机读取4KB数据

150,000ns(150μs)1.7days

从内存顺序读取1MB数据

250,000ns(250μs)

2.9days
数据包在同数据中心一个往返500,000ns(500μs)5.8days

从SSD(1GB/s)顺序读取1MB数据

1,000,000ns(1ms)11.6days

磁盘寻道

10,000,000ns(10ms)

3.8months

从磁盘顺序读取1MB数据

20,000,000ns(20ms)

7.9months

数据包从美国到荷兰一个往返

150,000,000ns(150ms)

4.75years

表格第三列将耗时数据提升10亿倍,换算成大家更容易看的单位。

这份数据的最初来源为 Peter Norvig 的文章:Teach Yourself Programming in Ten Years,地址:http://norvig.com/21-days.html。

伯克利的 Colin Scott 根据这份数据,通过一定的算法,制作了一个可以根据时间的推移而变化的网站,地址为:https://colin-scott.github.io/personal_website/research/interactive_latency.html,源码中注释有详细解释计算逻辑,例如网络带宽是按每2年增加1倍,DRAM带宽按每3年增加一倍。

根据 Colin Scott 的图表来看,到2021年,网络带宽、内存、SSD、磁盘,都有数量级的提升,而 CPU 相关的一二级缓存变化不大,有兴趣的可以自己点进去看一看。

看这些数据的目的


首先,这些数据肯定不是完全准确的,受限于众多环境因素的影响,其实很难有所谓的准确数字。

我们看这些数据更多是了解每个操作的耗时量级,各个操作之间的数量级比率,从而对于我们工作中接触到的一些相关知识有初步的概念。

而我将这个数据放在性能优化系列文章的开篇,主要想先传达给各位同学几个概念:

1)CPU非常非常快


CPU执行大部分简单指令只需要1个时钟周期,我用个人电脑测试时,CPU可以睿频到4.40GHz(见第2点的测试图),也就是说此时执行一个简单指令需要的时间大约是1/4.4ns,也就是0.23ns(纳秒)。

这是什么概念了,举个简单的例子,即使是真空中传播的光,在0.23ns内也只能走不到7厘米。

2)内存很快了,但是相比CPU来说还是太慢了


CPU和内存之间的瓶颈通常称为冯·诺伊曼瓶颈。具体差别有多大了,我用自己的电脑做了个简单的测试。

我电脑是今年刚买的,硬件应该都还比较新,但是配置比较普通,仅供参考。

CPU配置是 11th Gen Intel Core i5-11400F@2.60GHz,睿频4.40GHz,测试结果看也确实跑到了4.40GHz了,内存配置是 DDR4 3200MHz。

测试结果如下图所示:

从上图看,内存的读取速度为41GB/s,感觉还是挺快的,但是L1 Cache为3TB/s,一比较,相差还是很大。

如果CPU按4.40GHz来算,执行一个简单指令需要的时间大约是0.23ns(纳秒),而内存的延迟是88.7ns,相当于CPU去内存里取一个字节,需要等待386个周期,可以看出,内存相较于CPU来说,确实太慢了。

这也是为什么引入了L1、L2、L3缓存的原因,不过这边我们不深入去研究这些东西,只是对CPU和内存的性能差距有个大概概念。

3)磁盘性能非常非常慢


这个大家估计大家都知道,具体有多慢了,我这边在用自己的电脑做了个简单的测试。

我电脑刚好有两块硬盘,一块256GB的SSD(固态硬盘),一块1T的HDD(机械硬盘)。

SSD测试结果如下图所示:

忽略队列(Q)和线程(T)的影响,顺序读(SEQ)的性能为1535.67MB/s,随机读(RND)的性能为49.61MB/s。

对比下上面内存的性能41GB/s,尽管是SSD,性能还是存在数量级的差距,另一个就是随机读的性能相比顺序读也是存在数量级的差距。

HDD测试结果如下图所示:

忽略队列(Q)和线程(T)的影响,顺序读(SEQ)的性能为183.49MB/s,随机读(RND)的性能为0.6MB/s。

对比下上面SSD的性能:顺序读1535.67比183.49,存在一个数量级的差距,随机读49.61比0.6,存在两个数量级的差距。

而HDD顺序读和随机读的性能差距相比SSD就比较严重了,大概有300倍。简直惨不忍睹,不过相信现在的服务器应该基本都是SSD了。如果发现自己公司服务器的磁盘还是HDD,那就赶紧溜吧。

4)磁盘顺序I/O比随机读I/O快很多


这个在上面的测试也看出来了,都是数量级上的差距,特别是在以前的HDD上。有不少技术就是利用了顺序I/O性能好的特点来提升性能,典型的有:kafka顺序写消息、Leveldb和RocksDB底层使用的LSM-Tree等。

5)网络传输也是比较耗时的,基本都是毫秒级别


在开始的表格中可以看到,在同数据中心一个往返,需要0.5ms。

如果是跨城市就更久了,这个相信也不难理解,毕竟信号要顺着网线爬,距离越远,当然所需时间就越久了。

下图是上海到一些城市进行PING操作所需的时间,可以看到张家口已经需要30ms左右了,这也差不多就是北上的延迟。

这也是为什么我们在服务器的路由策略上通常会优先使用同机房优先、同中心优先的策略。

这让我想到我之前碰到的一个问题,当时是一个新服务在测试,数据库基本没数据,测试场景也是很简单的增删改查,但是接口的性能就是很差,动不动就上百毫秒。

仔细看了调用链后,发现每次DB操作都需要30ms左右,看了下机房分布后,发现是应用服务器和数据库服务器跨城市了,一个在北京一个在上海,导致会有固定30ms左右的延迟。将两者换到同机房后,基本就是1ms了。

总结

======

本文着重介绍了业务开发在做性能优化需要掌握的一些核心概念,之所以放在最先介绍,是因为在我做性能优化的过程中,发现绝大多数性能问题都是由于网络I/O和磁盘I/O引起的。对这些概念心中有数后,有利于我们更快的定位出性能瓶颈,从而更快的解决问题。

技术学习总结

学习技术一定要制定一个明确的学习路线,这样才能高效的学习,不必要做无效功,既浪费时间又得不到什么效率,大家不妨按照我这份路线来学习。

最后面试分享

大家不妨直接在牛客和力扣上多刷题,同时,我也拿了一些面试题跟大家分享,也是从一些大佬那里获得的,大家不妨多刷刷题,为金九银十冲一波!

2378705)]

[外链图片转存中…(img-T1KBurP4-1714702378706)]

最后面试分享

大家不妨直接在牛客和力扣上多刷题,同时,我也拿了一些面试题跟大家分享,也是从一些大佬那里获得的,大家不妨多刷刷题,为金九银十冲一波!

[外链图片转存中…(img-QSNbcZDt-1714702378706)]

[外链图片转存中…(img-YdmnHxSx-1714702378706)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 12
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值