本文是 Java 低延迟编程系列文章的第一篇。读完本文,您将掌握如下概念:算法
什么是延迟,做为开发者为何要关心延迟?编程
如何描述延迟,数据中的百分比意味着什么?浏览器
什么因素会形成延迟?缓存
闲话少说,让咱们开始吧。性能优化
1. 什么是延迟,为何延迟很重要?网络
延迟能够简单定义为执行一个操做耗费的时间。数据结构
“操做(operation)”是一种宽泛的说法,在这里我指的是软件系统中值得测量的行为,以及某个时间点该行为的一次执行过程。架构
例如,在典型 Web 应用中,操做能够是从浏览器提交查询并查看搜索结果;在交易应用程序中,能够是金融交易工具收到价格变更后自动向交易所发送买入卖出指令。一般,操做花费的时间越短,对用户的好处越大。用户更喜欢那些不须要等待的网络应用。回想当初,谷歌比同时代其余搜索引擎最大的优点就是快速搜索体验。交易系统对市场变化的反应越快,交易成功的几率就越高。数以百计的交易公司沉迷于让他们的交易引擎成为华尔街上延迟最低的系统,并所以从中得到竞争优点。并发
不夸张地说,在高风险的地方,下降延迟能够决定一家企业的成败!app
2. 如何描述延迟?
每一个操做都有延迟,一百种操做有一百种延迟。所以,不能使用像“操做数/秒”或“秒数/操做”这种单一的指标描述系统延迟,由于这只能用于描述某种操做的单次运行。
乍一看,能够把延迟定义为全部同类操做的平均值。这可不是什么好主意。
取平均值有什么问题吗?请考虑下面这张图:
有几个操做度超过了60毫秒的 SLA 目标(其实是7个),但平均响应时间却位于 SLA 范围内。一旦采用平均响应时间,红色区域内的全部异常值都会被忽略。然而,忽略的这部分异常值偏偏是对软件工程师来讲最重要的数据,即须要关注和梳理的系统性能问题。更糟糕的是,隐藏在这些数据背后的问题在实际生产环境中每每会发生。
另外值得注意的是,实际上不少延迟测量结果可能会像上图看到的那样,偶尔会看到一些随机的严重异常值。延迟历来不遵循正常分布、高斯分布或者泊松分布,你看到更多的多是多重模态分布延迟。实际上,这就是为何用平均值或标准差来讨论延迟是无效的。
延迟最好用百分比描述。
什么是百分位数?考虑一组数字,第 n 个百分位数(其中 `0 < n < 100`)将其分为两个部分,较低的部分包含 n% 的数据,较高的部分包含 (100 - n)% 的数据。所以,这两部分的数据总和为 100%。
例如,50%是指一半低于50%,另外一半高于50%。百分比更广为人知的说法是中位数。
让咱们举几个测量延迟的例子。90%的延迟为75毫秒,意味着100个操做中有90个操做延迟最多为75毫秒,而其他的操做,即100 - 90 = 10,延迟至少为75毫秒。
若是进一步补充,98%延迟170毫秒,这意味着100个操做中有2个操做的延迟达到或超过170毫秒。
若是再进一步补充,99%延迟313毫秒,这意味着每100个操做中有1个操做与其余操做相比有更大的延迟。
事实上,许多系统表现出这样的特征,即便百分比增长延迟也会显著增加。
为何要担忧长尾延迟呢?个人意思是,若是每100个操做中只有1个操做有较高延迟,那么系统性能还不够好吗?
好吧,为了有一个直观的印象,请想象下面这个场景。一个热门网站,90%延迟1秒、95%延迟2秒、99%延迟25秒。假设网站全部页面日浏览量超过100万,也就是说某个页面会有超过10000次加载超过25秒。这时候用户可能会打着哈欠关闭浏览器转而去干别的事情,更糟糕的状况他们会向亲朋好友吐槽此次糟糕的体验。任何在线业务都负担不起这样的长尾延迟。
3. 致使延迟的缘由是什么?
最简短的回答是:一切皆有可能!
延迟“抖动”会产生特有形状、出现随机离群值,可归因于下面这些事情:
硬件中断
网络/IO延迟
管理程序暂停
操做系统活动,例如内部结构重建、刷新缓冲等
上下文切换
垃圾收集暂停
这些事件一般是随机的,并不遵循正态分布。
另外,从更高的层次来看 Java 程序运行:
(管理程序、容器对于裸机硬件是可选的,但在虚拟化或云环境中与延迟密切相关)
减小延迟与如下因素密切相关:
CPU/缓存/内存架构
JVM 架构和设计
应用程式设计:并发、数据结构算法和缓存
网络协议等
上面的图中每一层都很复杂,大大增长了性能优化所需的知识和专业技能,也是时刻须要考虑成本、时间合理性的缘由。
但这就是性能工程如此有趣的缘由!
咱们的挑战是,让应用对所需的每一次操做执行延迟老是保持在合理的较低水平。
提及来容易,作起来难!