【系统性能优化】必知的一些关键数字(CPU仅1s,磁盘1个月,TCP包重传100年)

Google AppEngine Numbers

以下这组数字,来自于Brett Slatkin在2008年谷歌I/O大会的演讲《Building Scalable Web Applications with Google App Engine》。

英文原文:
http://highscalability.com/blog/2009/2/18/numbers-everyone-should-know.html

演讲视频和PPT:
https://sites.google.com/site/io/building-scalable-web-applications-with-google-app-engine

写操作是昂贵的

  • 数据存储是事务性的:写操作需要进行磁盘访问;
  • 磁盘访问,意味着需要进行磁盘寻道;
  • 经验法则:一次磁盘寻道需要10ms;
  • 简单的数学计算:1s / 10ms = 100次寻道/s(最大值);
  • 影响因素包括:
    • 数据的大小和形式(数据实体有多少个属性,属性的大小,是否为索引属性等);
    • 分批进行处理(批量写入和读取)。

读操作是廉价的

  • 读操作要保证一致性,但不需要具备事务性;
  • 一旦从磁盘读取了数据,就可以很容易的将它缓存起来;
  • 而后续的所有读取操作,可以直接从内存中读取;
  • 经验法则:从内存中读取1MB数据需要250us(微秒);
  • 简单的数学计算:1s / 250us = 4000MB/s = 4GB/s(最大值);
    • 对于1MB的实体数据,1s可以读取4000次。

数字杂项

以下这组数字,来自于Jeff Dean在Google的Engineering All-Hands Meeting上的演讲。

  • 访问L1缓存:0.5ns;
  • 分支预测失败:5ns;
  • 访问L2缓存:7ns;
  • 对互斥量(Mutex)的加锁/解锁操作:100ns;
  • 访问主存:100ns;
  • 使用Zippy压缩1KB数据:10,000ns = 10us;
  • 通过1Gbps的网络发送2KB数据:20,000ns = 20us = 0.02ms;
  • 从内存中顺序读取1MB数据:250,000ns = 250us = 0.25ms;
  • 同一个数据中心的RTT(往返时间):500,000ns = 500us = 0.5ms;
  • 磁盘寻道:10,000,000ns = 10ms;
  • 从网络中顺序读取1MB数据:10,000,000ns = 10ms;
  • 从磁盘中顺序读取1MB数据:30,000,000ns = 30ms;
  • 发送一个包,从加拿大到荷兰的RTT:150,000,000ns = 150ms;

经验教训

  • 写操作的成本,是读操作的40倍;
  • 全局共享数据非常昂贵。这是分布式系统的基本限制。对共享对象的大量写操作产生的锁竞争,会由于事务的串行化和缓慢而导致性能下降。
  • 支持可扩展写的架构;
  • 尽可能消除写入的竞争;
  • 尽可能让写操作并行化。

时间

响应时间

一次操作完成的时间。包括用于等待和服务的时间,也包括用来返回结果的时间。

也就是说,响应时间包括了(操作前等待的)延时和操作时间(执行指定操作所花费的时间)。

例如执行一个网络请求。需要先等待网络连接的建立,这个是请求的延时。然后执行实际的请求操作,这个就是操作时间。

延时

延时,是指操作中用来等待服务的时间,即操作执行之前所要的等待时间。在某些情况下,它可以指整个操作时间,等同于响应时间。

延时可以在不同的点进行测量,我们通常要指明延时测试的对象。

例如加载一个网页,从三个不同点测得的时间如下:

  • DNS延时。指整个DNS操作的时间;
  • TCP连接延时。指连接的初始化,即TCP三次握手;
  • TCP数据传输时间。

时间单位

时间的量级和缩写如下表所示:

(《性能之颠》)

系统的各种延时

系统各组件的操作所处的时间量级差别巨大,大到了难以体会的地步。

下表提供的延时示例,从访问3.3GHz的CPU寄存器的延时开始,阐释了我们所打交道的时间量级的差别。

表中是发生单次操作的时间均值,为了能有更为直观的感受,进行如下等比放大:

一次寄存器访问时间0.3ns(十亿分之一秒的三分之一),(放大后)相当于现实生活中的1秒。

注意观察相对时间比例这一列,体会一下各组件之间延时的巨大差异。

(《性能之颠》)

磁盘IO延时

磁盘I/O的时间尺度千差万别,从几十微秒到数千毫秒。

下表列出了磁盘I/O延时时间可能出现的一个大致范围。如果想得到准确和时下的数值,请查阅磁盘供应商的文档,并自己做一些微基准测试。

为了更好地演示相关的时间数量级,表中”比例”一列以在理想状况下磁盘缓存命中时间为1s,按比例放大

一块磁盘可以返回两种延时:

  • 一种是磁盘缓存命中(低于100us);
  • 另一种是缓存未命中(1~8ms,甚至更慢,取决于访问模式和磁盘类型)。

由于这两种延时磁盘都返回,以一个平均延时来表达(例如iostat(1))难免有误导之嫌。事实上这是一种双峰分布。

(《性能之颠》)

常用系统操作响应时间表

(《大型网站技术架构》)

常用硬件性能参数

对于15000转的SATA盘的顺序读取,带宽可以达到100MB以上。

磁盘带宽为100MB,那么读取1MB要10ms(1000ms/100MB=10ms/MB)。

如果磁盘寻道时间为10ms,则顺序读取1MB数据的时间为:

寻道时间+数据读取时间=10ms+10ms=20ms。

(《大规模分布式存储系统》)

这组参数,看起来应该是参考了开篇中Google的数据。

总结

文中所提到的这些数据,可以拿来做架构设计和技术选型时评估使用。

如果需要关注具体的数值,以生产环境的实测数据为准。

读取1MB数据

  • 从网络中顺序读取:10ms。1秒可以读取100次,或是1s最大读取100M(1000/10=100)。
  • 从磁盘中顺序读取:30ms。1秒可以读取33次,或是1s最大读取33M(1000/30=33)。
  • 从内存中顺序读取:0.25ms。1秒可以读取4000次,或是1s最大读取4G(1000/0.25=4000)。

访问时间数量级比较

为便于理解记忆,我们这里只是关注和对比各组件之间数量级上的差异:

  • 访问CPU L1缓存:1ns;
  • 访问主存:100ns。约为访问CPU L1缓存时间的100倍;
  • 访问机械磁盘:10ms = 10,000,000ns。约为访问主存时间的10w倍;
  • 访问固态磁盘:100us = 100,000ns。约为访问机械磁盘时间的1/100倍,访问主存时间的1000倍;

参考

http://highscalability.com/blog/2009/2/18/numbers-everyone-should-know.html

《性能之颠》

《大规模分布式存储系统》

《大型网站技术架构》


---转载本站文章请注明作者和出处 二进制之路(binarylife.icu),请勿用于任何商业用途---

留下评论