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

简介: 交流群里最常听到的一句话就是:我项目太垃圾了,面试怎么办。说实话,我听了也感同身受,因为我也是这么走过来的。而且,几乎大部分人都会经历这个过程。所以,不多说了,安排。

目录

前言

正文

看这些数据的目的

1CPU非常非常快

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

3)磁盘性能非常非常慢

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

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

总结

最后

推荐阅读


前言


交流群里最常听到的一句话就是:我项目太垃圾了,面试怎么办。说实话,我听了也感同身受,因为我也是这么走过来的。而且,几乎大部分人都会经历这个过程。所以,不多说了,安排。


之所以挑性能优化这个方向,主要有几个原因:

1)性能优化是我很感兴趣的一个方向,同时在过去几年,我在这个方向上积累了一些经验,可以说,我之前的面试,项目上几乎是靠性能优化一招走遍天下。因此,我觉得可以拿出来和大家分享一下。

2)性能优化非常通用,几乎对于所有线上项目都可以适用,大家掌握了之后,立马可以到项目中实践起来。我想,应该不存在不需要性能优化的项目,除非你的项目只有“Hello world”

3)性能优化大部分内容非常简单,几乎没有门槛,经验较浅的同学也很容易上手,同时性能优化也适用二八原则:掌握20%的内容,足以解决80%的问题。

4)性能优化很容易拿到结果,稍微有经验点的同学应该知道,做需求最怕拿不到结果,性能优化就不一样了,都是很直白的数字。1小时的任务,我优化成5分钟,性能提升就是十来倍,简单粗暴。

不多说了,开怼。


正文



文章的标题来源于 Jeff Dean 在谷歌的内部一次分布式系统的演讲,英文标题为:Numbers Everyone Should Know

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

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

注:1μs = 1000ns1ms = 1000μs


操作

耗时/延迟

耗时*10亿

一级缓存读取(L1

0.5ns

0.5s

分支错误预测

5ns

5s

二级缓存读取(L2

7ns

7s

互斥锁的加锁解锁

25ns

25s

内存寻址

100ns

100s

Zippy压缩1KB数据

3000ns3μs

50min

1Gbps网络上发送1KB数据

10,000ns10μs

2.8h

SSD1GB/s)随机读取4KB数据

150,000ns150μs

1.7days

从内存顺序读取1MB数据

250,000ns250μs

2.9days

数据包在同数据中心一个往返

500,000ns500μs

5.8days

SSD1GB/s)顺序读取1MB数据

1,000,000ns1ms

11.6days

磁盘寻道

10,000,000ns10ms

3.8months

从磁盘顺序读取1MB数据

20,000,000ns20ms

7.9months

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

150,000,000ns150ms

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 相关的一二级缓存变化不大,有兴趣的可以自己点进去看一看。


看这些数据的目的


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

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

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


1CPU非常非常快


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

测试结果如下图所示:

image.png

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


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


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


3)磁盘性能非常非常慢


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

我电脑刚好有两块硬盘,一块256GBSSD(固态硬盘),一块1THDD(机械硬盘)。

SSD测试结果如下图所示:

image.png

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

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

HDD测试结果如下图所示:

image.png

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

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

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


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

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


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

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

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

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

image.png

image.png

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

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

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


总结


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


有同学可能会问,下一篇文章什么时候,不会又是两个月后吧?


答:跟大家聊下为什么更新间隔这么久,一个是确实变懒了,这个毋庸置疑,有一些其他的事情就忘了这边,比如从几个月前开始我坚持每天健身,当然归根到底有很大的原因是动力的问题。


另外一个就是工作确实比较忙,现在做的项目比较有挑战,基本都是几十万上百万的QPS,几十亿的数据量,很多问题都不可同日而语,因此要做的事情很多,挑战比较大,所以需要花比较多的时间去思考和维护。


然后,道理是这样的,很多同学都有白嫖的习惯,这个我不反对,因为我自己也经常白嫖。但是如果你确实觉得这个系列文章对你有帮助,你希望能加快更新速度,那最好的方式是给我点反馈,一键三什么你懂的。


我需要有反馈才能知道文章对大家是否有帮助,如果好的反馈多了,我知道文章对大家帮助很大,自然就会更新的勤快点,通宵什么的说不定也干的出来,我狠起来我自己都怕。


最后



我是囧辉,一个坚持分享原创技术干货的程序员


推荐阅读


Java 基础高频面试题(2021年最新版)

Java 集合框架高频面试题(2021年最新版)

面试必问的 MySQL,你懂了吗?

面试必问的线程池,你懂了吗?

目录
打赏
0
0
0
0
14
分享
相关文章
Go语言性能优化实践:案例分析与解决方案
【2月更文挑战第18天】本文将通过具体的案例分析,探讨Go语言性能优化的实践方法和解决方案。我们将分析几个典型的性能瓶颈问题,并详细介绍如何通过优化代码、调整并发模型、改进内存管理等方式来提升程序的性能。通过本文的学习,读者将能够掌握一些实用的Go语言性能优化技巧,为实际项目开发中的性能优化工作提供指导。
前端开发的速度之道:性能优化技巧
在前端开发中,性能优化是至关重要的。本文将介绍一些高效的前端开发技巧,帮助开发者提升网站或应用程序的性能和用户体验。通过合理的代码编写、资源加载策略、图片优化等手段,你可以轻松优化前端性能,提升页面加载速度和响应能力。
探索前端开发的性能优化之道
在当今数字化时代,快速加载和高效运行的网页对于用户体验至关重要。本文将介绍一些前端开发中的性能优化技巧,帮助开发人员提升网页的加载速度和响应能力,提供更流畅的用户体验。
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
101 1
架构师必备10大接口性能优化秘技
【11月更文挑战第25天】在软件开发中,接口性能优化是架构师必须掌握的关键技能之一。一个高效的接口不仅能够提升用户体验,还能减少服务器资源消耗,提高系统稳定性。本文将介绍10大接口性能优化秘技,并通过Java示例代码展示这些技巧在实际业务场景中的应用。
71 3
【C/C++ 性能优化】循环展开在C++中的艺术:提升性能的策略与实践
【C/C++ 性能优化】循环展开在C++中的艺术:提升性能的策略与实践
822 0
安卓应用开发中的性能优化实践
【8月更文挑战第31天】在安卓的世界里,性能是王道。本文将带你深入理解如何通过代码优化和工具使用来提升你的安卓应用性能。我们将一起探索内存管理、布局优化、多线程处理等关键领域,并配以实用的代码示例,让你的应用飞一般地运行起来!
Java并发编程:最佳实践与性能优化
Java并发编程:最佳实践与性能优化
利用阿里云进行性能优化:实践案例分享
在开发在线教育平台过程中,我们遇到了由于用户访问量增加而导致的性能瓶颈问题。通过使用阿里云的多种服务,包括RDS数据库、ECS弹性扩展、SLB负载均衡、OSS存储和CDN加速,我们对数据库、应用服务器和静态资源加载进行了全面优化。优化后的系统性能显著提升,数据库查询速度提高了60%,服务器负载下降了40%,静态资源加载时间减少了70%,从而极大改善了用户体验。本文详细介绍了问题分析、具体解决方案及其实施效果,旨在为其他开发者提供有价值的参考。
328 3
|
9月前
|
一次性能优化实践
【5月更文挑战第21天】为解决在线教育平台在高并发下数据库查询响应时间增加的问题,开发者采用Redis缓存策略。通过数据分层、LRU淘汰策略、异步更新及监控调优,成功提升性能,缓存命中率超90%,页面加载时间从3秒降至1秒,改善了用户体验。此实践强调了合理缓存策略、监控调优以及考虑数据访问模式在系统设计中的重要性。
87 2
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等