关于CPU、内存、硬盘及网络传输速度的整理

前言

最近看了一些关于CPU、内存、硬盘及网络传输速度相关的博客:
https://cizixs.com/2017/01/03/how-slow-is-disk-and-network/
https://gist.github.com/hellerbarde/2843375

了解了一些常见的系统操作的耗时,在此进行一下总结
有助于当我们见到一些系统耗时统计数据时,能够粗略的判断其是否存在性能问题

数据

废话不多说,我们直接看以下表格

| 操作 | 大致耗时 | 耗时级别 | 时间量级倍数 | 类比人类时间 |
| - | - | - | - |
| CPU执行一个指令 | 0.38ns | 纳秒 | - | 1s |
| CPU读取一级缓存 | 0.5ns | 纳秒 | - | 1.3s |
| CPU分支预测错误 | 5ns | 纳秒 | 十倍 | 13s |
| CPU读取二级缓存 | 7ns | 纳秒 | 十倍 | 18.2s |
| 互斥锁加锁与解锁 | 25ns | 纳秒 | 百倍 | 65s |
| 内存寻址 | 100ns | 纳秒 | 千倍 | 260s |
| CPU上下文切换(系统调用) | 1.5us | 微秒 | 万倍 | 65分钟 |
| 1Gbps网络传输2K数据 | 20us | 微秒 | 十万倍 | 14.4小时 |
| SSD随机读取 | 150us | 微秒 | 百万倍 | 4.5天 |
| 内存读取1MB的连续数据 | 250us | 微秒 | 百万倍 | 7.5天 |
| 同一个数据中心网络上跑一个来回 | 500us | 微秒 | 百万倍 | 15天 |
| SSD读取1MB的连续数据 | 1ms | 毫秒 | 千万倍 | 1个月 |
| 磁盘寻址 | 10ms | 毫秒 | 亿倍 | 10个月 |
| 磁盘读取1MB的连续数据 | 20ms | 毫秒 | 亿倍 | 20个月 |
| 执行一个ping报文平均时间 | 150ms | 毫秒 | 十亿倍 | 12.5年 |
| 虚拟机重启 | 4s | 秒 | 百亿倍 | 300多年 |
| 物理重启 | 5min | 分钟 | 千亿倍 | 2万5千年 |

在操作的耗时被量化之后,我们可以看到一些很有趣的现象:

  • CPU相关的操作,执行指令以及读取CPU缓存啥的,基本都是纳秒级别的
  • 如果CPU需要去读取内存数据,耗时将是CPU相关操作耗时的千倍,基本上到达了微秒级别,CPU和内存之间的速度瓶颈被称为冯诺依曼瓶颈
  • 如果需要去执行io操作,即使是较快的SSD,耗时也是内存操作耗时的千倍,基本上到达了毫秒级别
  • 如果是在更慢的磁盘上执行io操作,耗时也是SSD操作耗时的百倍,妥妥的毫秒级别
  • 若是需要执行网络请求去获取数据,则耗时是SSD操作耗时的千倍,稍有不慎就会上到秒的级别

由此可见,基本上获取数据的存储来源每上一个等级,时间量级也要跟着上一个等级

1
2
CPU -> 内存 -> SSD -> 磁盘 -> 网络
纳秒 -> 微秒 -> 毫秒 -> 毫秒 -> 秒

最后再补充一个有趣的问题,看下CPU的分支预测是如何影响到程序的执行时间的
为何排序前后的数组求和耗时不一样:
https://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-processing-an-unsorted-array