本文是 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 架構和設計
應用程式設計:併發、數據結構算法和緩存
網絡協議等
上面的圖中每一層都很複雜,大大增長了性能優化所需的知識和專業技能,也是時刻須要考慮成本、時間合理性的緣由。
但這就是性能工程如此有趣的緣由!
咱們的挑戰是,讓應用對所需的每一次操做執行延遲老是保持在合理的較低水平。
提及來容易,作起來難!