成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

開(kāi)發(fā)運(yùn)維必知的21件事:認(rèn)清性能問(wèn)題

運(yùn)維 系統(tǒng)運(yùn)維 測(cè)試
對(duì)于開(kāi)發(fā)者、技術(shù)管理者、架構(gòu)師、系統(tǒng)分析師和項(xiàng)目經(jīng)理來(lái)說(shuō),創(chuàng)建具備高性能特征的復(fù)雜軟件都是一件極其困難的事。 然而,通過(guò)了解一些基本原理、性能問(wèn)題的解決和預(yù)防可以更簡(jiǎn)單、可靠。 本文講述了這些基本原理,涵蓋了一系列的目標(biāo)、術(shù)語(yǔ)、工具和決策,綜合利用好它們來(lái)最大可能的創(chuàng)建一個(gè)長(zhǎng)期、有效的高性能應(yīng)用。

 今年越來(lái)越多開(kāi)發(fā)者開(kāi)始關(guān)注移動(dòng)應(yīng)用性能管理和性能監(jiān)測(cè),我們找到一位國(guó)外資深的開(kāi)發(fā)者對(duì)性能的相關(guān)理論,希望各位喜歡。

1. 公理化方法

當(dāng)我在1989年加入 oracle 公司時(shí),解決性能問(wèn)題(人們通常說(shuō)的 oracle 調(diào)優(yōu))是很困難的。 只有少部分人聲稱他們很擅長(zhǎng)這個(gè),很多人都去咨詢他們。 當(dāng)時(shí),我進(jìn)到 oracle 調(diào)優(yōu)這個(gè)領(lǐng)域時(shí),我完全沒(méi)準(zhǔn)備好。 最近我又開(kāi)始對(duì) mysql 進(jìn)行調(diào)優(yōu),這看起來(lái)和我20年前在 oracle 公司做的差不多。

它讓我想起了當(dāng)我13歲剛接觸代數(shù)學(xué)時(shí)是多么的困難。 在那個(gè)年齡我只能依靠“數(shù)學(xué)直覺(jué)”來(lái)解決類似 3x + 4 = 13 這樣的方程。 問(wèn)題是我們之中大部分人都沒(méi)有所謂的“數(shù)學(xué)直覺(jué)”。 我記得當(dāng)看到這樣的問(wèn)題: 3x + 4 = 13 求解x,只能采用試錯(cuò)法偶然發(fā)現(xiàn) x 應(yīng)該是3。

試錯(cuò)法給我的感覺(jué)雖然能解決一些簡(jiǎn)單的方程式,但很慢而且不爽。 一旦等式稍有變化如 3x + 4 = 14,試錯(cuò)法就不能適應(yīng)。 那么該怎么辦呢?當(dāng)時(shí)我沒(méi)有好好思考過(guò),直到15歲時(shí)James R. Harkey指引我走上正確的道路。
Harkey 先生教會(huì)我使用公里方法來(lái)解決代數(shù)方程問(wèn)題。 他給我們展示了一系列的步驟(還給了我很多家庭作業(yè)進(jìn)行練習(xí))。 做作業(yè)時(shí)除了記錄下這些步驟,還要寫下我們是如何思考的。 這樣我們不僅自己想的很清楚,而且通過(guò)一系列可靠的,可重復(fù)的步驟來(lái)向閱讀我們作業(yè)的人證明了我們確實(shí)搞明白了。 Harkey 先生看到的我的作業(yè)像下面這樣:

	
3.1x + 4     = 13               待求解方程
3.1x + 4 - 4 = 13 - 4           減去相等的值
3.1x         = 9                加法逆運(yùn)算,化簡(jiǎn)
3.1x ∕ 3.1   = 9 ∕ 3.1          除以相等的值
x            ≈ 2.903            乘法逆運(yùn)算,化簡(jiǎn)求解

這就是 Harkey 先生教導(dǎo)的適用于代數(shù)學(xué)、幾何學(xué)、三角學(xué)和微積分的公理化方法。 由一系列符合邏輯的、可證明和審計(jì)的小步驟組成。 這是我第一次真正從數(shù)學(xué)中學(xué)到的東西。

自然,當(dāng)時(shí)我沒(méi)能認(rèn)識(shí)到其中的價(jià)值,但證明作為一種技能對(duì)我后來(lái)的成功至關(guān)重要。 我發(fā)現(xiàn)在生活中,知道一件事很重要,但能向別人講清楚(證明)更重要。 沒(méi)有好的證明技能,就很難成為一名好的顧問(wèn)、好的領(lǐng)導(dǎo)甚至好的員工。

我在上世紀(jì)90年代中期的目標(biāo)是為 oracle 性能優(yōu)化創(chuàng)建一套類似的、嚴(yán)格的公理化方法。 后來(lái)我將其擴(kuò)展到了 oracle 之外,建立了一套適用于所有計(jì)算機(jī)軟件性能優(yōu)化的公理化方法。 好吧,我發(fā)現(xiàn)并非所有人都喜歡這種說(shuō)法,那我們換一種說(shuō)法:

我們的目標(biāo)就是幫助你想清楚如何優(yōu)化你的軟件系統(tǒng)性能。

2. 什么是性能?
假如你去 google 下 performance 這個(gè)關(guān)鍵字,可能會(huì)得到5億個(gè)鏈接。 其中涉及的內(nèi)容范圍可能從自行車比賽到可怕的員工審查流程(如今很多公司已經(jīng)學(xué)會(huì)了避免這個(gè)流程)。 但假如我去 google 下 performance 這個(gè)關(guān)鍵字,大部分的首頁(yè)鏈接都會(huì)與這篇文章的主題有關(guān):計(jì)算機(jī)軟件執(zhí)行無(wú)論何種任務(wù)所花費(fèi)的時(shí)間。

任務(wù)這個(gè)詞是一個(gè)很適合的開(kāi)始。 任務(wù)是一個(gè)面向業(yè)務(wù)的工作單元。 任務(wù)能夠嵌套:打印發(fā)貨單是一個(gè)任務(wù),打印一張發(fā)貨單(一個(gè)子任務(wù))也是一個(gè)任務(wù)。 當(dāng)一個(gè)用戶說(shuō)起性能時(shí),他通常指的是系統(tǒng)執(zhí)行一系列任務(wù)所花費(fèi)的時(shí)間。 響應(yīng)時(shí)間是任務(wù)的執(zhí)行時(shí)長(zhǎng),用每個(gè)任務(wù)的時(shí)間來(lái)度量,像:每點(diǎn)擊秒數(shù)。 例如我用 google 搜索關(guān)鍵字 performance 的響應(yīng)時(shí)間是 0.24 秒。 這個(gè)數(shù)據(jù)來(lái)自我的瀏覽器渲,它渲染完google網(wǎng)頁(yè)花費(fèi)的時(shí)間,那么很明顯,這量化了我對(duì) google 性能的直覺(jué)感知。

一些人對(duì)另外一個(gè)性能指標(biāo)很感興趣:吞吐量。 吞吐量是在一個(gè)特定時(shí)間段內(nèi)完成的任務(wù)的計(jì)數(shù),例如:每秒點(diǎn)擊數(shù)。 通常為一群人提供服務(wù)比為個(gè)別人提供服務(wù)的人更關(guān)心吞吐量。 例如,一個(gè)獨(dú)立會(huì)計(jì)會(huì)更關(guān)心日?qǐng)?bào)的響應(yīng)時(shí)間是否會(huì)導(dǎo)致今晚需要加班,而會(huì)計(jì)部的經(jīng)理更關(guān)心系統(tǒng)的是否能支撐所有的會(huì)計(jì)處理完今天的數(shù)據(jù)。

3. 響應(yīng)時(shí)間 VS. 吞吐量
通常來(lái)講,響應(yīng)時(shí)間和吞吐量是一個(gè)倒數(shù)關(guān)系(響應(yīng)時(shí)間越長(zhǎng)吞吐越低),但這并不確切。 實(shí)際情況更微妙、復(fù)雜一些。

例: 假如,在一些性能基準(zhǔn)測(cè)試中,你的系統(tǒng)的測(cè)量結(jié)果是每秒能處理1000個(gè)任務(wù),那么用戶的平均響應(yīng)時(shí)間是多少? 你可能會(huì)說(shuō)平均響應(yīng)時(shí)間等于 1 / 1000 = .001 秒/每任務(wù),但它真不是這樣的。 假如在你的系統(tǒng)內(nèi)部擁有1000個(gè)相同的、獨(dú)立的、并行的服務(wù)執(zhí)行通道,每個(gè)通道都在等待請(qǐng)求到來(lái)并提供服務(wù)。 在這種情況下,每個(gè)請(qǐng)求其實(shí)花費(fèi)了1秒。 現(xiàn)在我們知道,平均響應(yīng)時(shí)間其實(shí)應(yīng)該在每任務(wù)0秒到1秒之間。 但是我們不能僅僅從吞吐量的測(cè)量數(shù)據(jù)中推導(dǎo)出平均響應(yīng)時(shí)間。 (事實(shí)上存在數(shù)學(xué)模型從吞吐量推導(dǎo)出平均響應(yīng)時(shí)間,但這個(gè)模型要求更多的輸入?yún)?shù),而不僅僅是吞吐量) 你必須單獨(dú)測(cè)量它。

反過(guò)來(lái)說(shuō)也是一樣的,你應(yīng)該能從我上面給出的例子中得到啟發(fā)。 下面是一個(gè)更有趣的例子。

例: 你的客戶要求一個(gè)新任務(wù)必須滿足在單核 cpu 的計(jì)算機(jī)上達(dá)到每秒100的吞吐量。 假如這個(gè)新任務(wù)在客戶的系統(tǒng)上執(zhí)行一次需要 0.001 秒。 那么你的程序能夠滿足客戶要求的吞吐量么? 你可能會(huì)說(shuō),跑一次這個(gè)任務(wù)只需要千分之一秒,那么在一秒內(nèi)完成100次顯然是綽綽有余的。 恩,是的,你很正確,假如這個(gè)任務(wù)被很好的串行化了。 例如,你的程序處理100個(gè)任務(wù)執(zhí)行請(qǐng)求是在一個(gè)循環(huán)中,一個(gè)接一個(gè)的執(zhí)行,那就是正確的。 但是如果這100個(gè)任務(wù)到達(dá)你的系統(tǒng)是完全隨機(jī)的來(lái)自100個(gè)不同的用戶,那該怎么辦呢? cpu 調(diào)度器和串行資源(oracle 的閂和鎖,內(nèi)存可寫緩沖區(qū)訪問(wèn))這些糟糕的實(shí)際情況會(huì)嚴(yán)格限制你的并發(fā)吞吐量低于每秒100。 最終,你可能會(huì)達(dá)到客戶的期望也可能達(dá)不到。 你不能僅僅從響應(yīng)時(shí)間推導(dǎo)出吞吐量,你必須單獨(dú)測(cè)量吞吐量。

所以,響應(yīng)時(shí)間和吞吐量不是那么簡(jiǎn)單的互為倒數(shù)關(guān)系。 你想要知道這兩個(gè)指標(biāo),就必須一起測(cè)量它們。
那么響應(yīng)時(shí)間和吞吐量到底哪一個(gè)更重要呢? 在一些場(chǎng)景下,說(shuō)哪一個(gè)都是合理的。 但在大多數(shù)情況下,兩者都同樣重要。 因?yàn)?,?duì)系統(tǒng)來(lái)說(shuō)它的業(yè)務(wù)需求通常是這樣的,在大于99%的情況下響應(yīng)時(shí)間要少于1秒,并且能支持10分鐘內(nèi)持續(xù)不低于1000的吞吐量。

4. 百分比指標(biāo)
在上一節(jié),我用了“大于99%”這樣的描述來(lái)表達(dá)對(duì)響應(yīng)時(shí)間的期望。 但大部分人可能更習(xí)慣于這樣的描述:“平均響應(yīng)時(shí)間少于 r 秒”。 但從經(jīng)驗(yàn)的角度,使用百分比方式更好。

例: 假如你對(duì)一些每天運(yùn)行在你的計(jì)算機(jī)上的任務(wù)的響應(yīng)時(shí)間的容忍極限是1秒。 進(jìn)一步假設(shè)表1列出了該任務(wù)執(zhí)行10次的測(cè)量值。 這兩個(gè)列表的平均響應(yīng)時(shí)間都是1秒。 哪一個(gè)你認(rèn)為更好? 
你看到雖然兩個(gè)列表?yè)碛型瑯拥钠骄憫?yīng)時(shí)間,但本質(zhì)上差別很大。 ListA 90%的響應(yīng)時(shí)間是低于1秒的,而ListB只有60%的時(shí)間是低于1秒的。 從用戶體驗(yàn)的角度來(lái)說(shuō),ListB表明會(huì)有40%的用戶會(huì)感到不滿意,而ListA僅有10%的不滿意率,雖然它們平均響應(yīng)時(shí)間相同。 ListA 90%的響應(yīng)時(shí)間是0.987秒,而ListB 90%的響應(yīng)時(shí)間是1.273秒。 因此使用百分比描述的響應(yīng)時(shí)間比平均響應(yīng)時(shí)間包含更多的信息量。

 

99.9%的跟蹤貨運(yùn)單的任務(wù)必須在0.5秒內(nèi)完成。

5. 問(wèn)題診斷
最近我被邀請(qǐng)去解決的一些性能問(wèn)題的描述都是些關(guān)于響應(yīng)時(shí)間的。 如:“過(guò)去只用不到1秒的時(shí)間就能完成X任務(wù),但是現(xiàn)在卻需要20秒。” 當(dāng)然,一些真正的問(wèn)題隱藏在其他一些問(wèn)題描述的表象背后,例如:“我們的系統(tǒng)變的很慢,完全沒(méi)法用了。”

雖然我經(jīng)常碰到類似這樣的表述,但并不意味著你應(yīng)該這樣去描述問(wèn)題。 首先你得清晰得描述問(wèn)題本身,才可能把它們弄清楚。 一個(gè)好辦法是去詢問(wèn),你想要達(dá)到得目標(biāo)狀態(tài)是怎樣的呢? 找到一些細(xì)節(jié),你可以用量化的方式來(lái)表達(dá)它們。 例如:執(zhí)行 X 任務(wù)大部分情況下都超過(guò)20秒,希望能在95%的情況下小于1秒。

理論上這聽(tīng)起來(lái)很棒,但要是你的用戶根本沒(méi)有很具體的可以量化的目標(biāo)呢? 或者你的用戶根本就不知道怎樣去量化,更糟糕的情況是你的用戶如果還有一些完全不切實(shí)際的期望怎么辦? 你如何知道到底什么是“可能的”,什么是“不切實(shí)際的”?
好吧,下面我們繼續(xù)探討這些問(wèn)題。

6. 序列圖
序列圖是一種UML(統(tǒng)一建模語(yǔ)言)中定義的圖形種類,用于表達(dá)對(duì)象間交互的發(fā)生順序。 序列圖特別適合用于可視化的表達(dá)響應(yīng)時(shí)間。 在圖1中,我們展示了一個(gè)由瀏覽器、應(yīng)用服務(wù)器和數(shù)據(jù)庫(kù)構(gòu)成的簡(jiǎn)單應(yīng)用系統(tǒng)的序列圖。
假如我們擴(kuò)展下序列圖的表示,讓請(qǐng)求和響應(yīng)之間距離表示服務(wù)該請(qǐng)求的消耗時(shí)長(zhǎng)。 在圖2中我展示了一個(gè)擴(kuò)展后的序列圖。

通過(guò)圖2,你可以很直觀的看到到底是哪個(gè)部分消耗了最多的時(shí)間。 你能直觀的感受到整個(gè)響應(yīng)時(shí)間在各個(gè)部分的構(gòu)成。 序列圖很好的幫助人們從概念上直觀的理解一個(gè)任務(wù)如何在系統(tǒng)各個(gè)部分之間順序流轉(zhuǎn)的。 序列圖也能很好的表達(dá)并行執(zhí)行的任務(wù)。 序列圖也是一個(gè)很棒的工具用于在業(yè)務(wù)層次分析性能問(wèn)題。
序列圖是很好的描述性能問(wèn)題的概念工具,但要把性能問(wèn)題分析清楚我們還需要其他的。 序列圖的問(wèn)題是,假設(shè)有個(gè)任務(wù)花費(fèi)了2468秒才執(zhí)行完成(大約41分鐘8秒)。 在這41分鐘里,應(yīng)用服務(wù)器和數(shù)據(jù)庫(kù)大約交互了322968次。 把這個(gè)過(guò)程畫(huà)成序列圖大概就是下面圖3的樣子:

在應(yīng)用服務(wù)器和數(shù)據(jù)庫(kù)之間有如此之多的箭頭,以至于你完全看不清細(xì)節(jié)了。 我們可能需要花費(fèi)數(shù)周才能畫(huà)完這個(gè)圖,但這并不是一個(gè)有效的方法。 序列圖雖然很好的概念可視化了任務(wù)的執(zhí)行流和時(shí)間流,但要仔細(xì)分析清楚響應(yīng)時(shí)間的問(wèn)題我們還需要?jiǎng)e的工具。

7. 性能剖析
對(duì)于像上述這種擁有大量調(diào)用交互的情況,序列圖不能很好的描述。 我們需要一種更方便的聚合視圖來(lái)更容易的理解到底哪個(gè)部分消耗了最多的時(shí)間。 表2給出了一個(gè)性能剖析的例子。 性能剖析是對(duì)響應(yīng)時(shí)間的表格化分解,按響應(yīng)時(shí)長(zhǎng)倒序排列如下。

例:表2中的性能剖析是很初級(jí)的,但它能告訴你top 8 的慢任務(wù)占用了2468秒。 從中你大概可以得到每個(gè)函數(shù)的響應(yīng)時(shí)長(zhǎng)占比。 也可以從中算出每個(gè)函數(shù)調(diào)用的平均響應(yīng)時(shí)間。

從表2的數(shù)據(jù)表明,大約70.8%的響應(yīng)時(shí)間消耗在了 DB:Fetch() 這個(gè)方法上。 如果你進(jìn)一步深入方法調(diào)用中會(huì)發(fā)現(xiàn) App:await_db_netIO() 方法與 DB:Fetch() 的一一對(duì)應(yīng)關(guān)系。 于是能知道每個(gè)部分消耗了多少時(shí)間,通過(guò)性能剖析你開(kāi)始能夠明確的回答像這樣的問(wèn)題: “這個(gè)任務(wù)需要運(yùn)行多長(zhǎng)時(shí)間?”從第5節(jié)你可以知道,對(duì)問(wèn)題診斷的第一步來(lái)說(shuō)這是一個(gè)很重要的問(wèn)題。

8. 阿姆達(dá)爾定律
性能剖析能幫你分析清楚性能問(wèn)題。 即便基恩·阿姆達(dá)爾在1967年沒(méi)有告訴我們阿姆達(dá)爾定律,你也可以在看到性能剖析表格時(shí)自己歸納出來(lái)。
阿姆達(dá)爾定律指出:

系統(tǒng)中對(duì)某一部件采用更快執(zhí)行方式所能獲得的系統(tǒng)性能改進(jìn)程度,取決于這種執(zhí)行方式被使用的頻率,或所占總執(zhí)行時(shí)間的比例

所以如果你嘗試改進(jìn)的部分只占總響應(yīng)間的5%,那么對(duì)總響應(yīng)時(shí)間的提高最多不會(huì)超過(guò)5%。 這意味著你改進(jìn)的部分在性能剖析列表中排位越高(假設(shè)它們按倒序排列),你獲得的收益就越大。 但這并不意味著你一定要按照性能剖析列表的順序從高到低進(jìn)行改進(jìn),這里你還需要考慮改進(jìn)的成本問(wèn)題。

例: 看下表3,它基本和表2一樣。 表3額外給出了你實(shí)施最好的改進(jìn)方案所能達(dá)到的效果以及相應(yīng)的實(shí)施成本。

那么你應(yīng)該先實(shí)現(xiàn)哪一項(xiàng)改進(jìn)呢?
阿姆達(dá)爾法則告訴我們改進(jìn)第一項(xiàng)的潛在收益最大,大約可以減少851秒(34.5% * 2468秒)。
但改進(jìn)第一項(xiàng)真的非常昂貴,那么改進(jìn)第二項(xiàng)也許能產(chǎn)生更多的凈收益。
這才是我們真正需要改進(jìn)的瓶頸所在,盡管它僅能節(jié)省大約303秒。

你首先實(shí)施哪一項(xiàng)改進(jìn),歸結(jié)于你對(duì)成本評(píng)估有多大把握, 簡(jiǎn)單省事的改進(jìn)的措施是否考慮了改進(jìn)可能造成的系統(tǒng)風(fēng)險(xiǎn)? 一個(gè)很簡(jiǎn)單的改進(jìn),例如調(diào)整了某個(gè)參數(shù),取消了一個(gè)索引可能會(huì)潛在的破壞了一些目前性能表現(xiàn)良好的功能,而你又完全沒(méi)考慮倒。 靠譜的成本評(píng)估則是展現(xiàn)你技術(shù)能力的另一個(gè)領(lǐng)域了。

另一個(gè)因素值得考慮的是,你可以通過(guò)一些小的成功來(lái)積累政治資本。 也許一些便宜低風(fēng)險(xiǎn)的改進(jìn)并不能帶來(lái)響應(yīng)時(shí)間的大幅度降低,但可以通過(guò)跟蹤記錄這些小改進(jìn)來(lái)印證你對(duì)響應(yīng)時(shí)間提升的預(yù)測(cè)。 在神話和迷信統(tǒng)治了數(shù)十年的軟件性能領(lǐng)域,這些對(duì)性能的預(yù)測(cè)和印證的跟蹤記錄,可以影響你的同事(工程師、經(jīng)理、客戶)并建立自己的信譽(yù),然后你才可能實(shí)施更昂貴的改進(jìn)方案。

最后提醒一句:當(dāng)你不斷取得勝利并建議實(shí)施成本更高、風(fēng)險(xiǎn)更大的改進(jìn)措施時(shí),可千萬(wàn)別掉以輕心。 信任是很脆弱的,你做了很多事情才取得信任,但可能只是因?yàn)橐淮未中拇笠獾腻e(cuò)誤就會(huì)摧毀它。

9. 偏斜度
當(dāng)你使用性能剖析時(shí),你會(huì)反復(fù)遇到類似這樣的衍生問(wèn)題。

例: 從表2中可以看到一共調(diào)用了322,968次 DB:fetch()方法,花費(fèi)了1748.229秒。 假如我們將調(diào)用量降低一半,那么響應(yīng)時(shí)間會(huì)降低多少?

答案絕對(duì)不會(huì)是降低一半,花點(diǎn)時(shí)間思考下面這個(gè)更簡(jiǎn)單點(diǎn)的例子。

例: 調(diào)用4個(gè)方法花費(fèi)了4秒鐘,那么減少為調(diào)用2個(gè)方法花費(fèi)多少時(shí)間?

答案依賴于我們省掉的調(diào)用到底是哪些方法。 你可能這樣假設(shè)了,每個(gè)方法的平均調(diào)用時(shí)間就是 4 / 4 = 1 秒。 但我可沒(méi)在問(wèn)題描述中告訴你的,每個(gè)方法的調(diào)用耗時(shí)是一樣的。

例: 假設(shè)下面兩種可能性,每個(gè)列表列出了4個(gè)方法調(diào)用的響應(yīng)時(shí)間
A = {1, 1, 1, 1}
B = {3.7, .1, .1, .1}
在列表A中響應(yīng)時(shí)間是一致的,所以無(wú)論我們省掉了哪兩個(gè)調(diào)用,最后響應(yīng)時(shí)間都能縮短到2秒。
但在列表B中,到底省掉哪兩個(gè)方法調(diào)用對(duì)響應(yīng)時(shí)間的影響是有很大差別的。
如果我們?nèi)サ纛^兩個(gè)調(diào)用,響應(yīng)時(shí)間縮短為0.2秒,提升了95%。
但如果我們?nèi)サ舻氖呛髢蓚€(gè)調(diào)用,響應(yīng)時(shí)間變?yōu)?.8秒,僅僅提升了5%。

偏斜度表達(dá)在一組值中的非一致性程度。 正是因?yàn)槠倍鹊拇嬖?,所以你沒(méi)法準(zhǔn)確的回答我在本節(jié)開(kāi)頭的問(wèn)題。 讓我們?cè)倩仡^看看這個(gè)例子,在不知道偏斜度的前提下,你只能回答響應(yīng)時(shí)間可能減少的范圍是在0到1748.229秒之間,這也是你能提供的最好的回答了。 盡管如此,假設(shè)你有一些額外的信息例如表4所示,你就能對(duì)最好和最壞的情況進(jìn)行估算。 進(jìn)一步說(shuō),假如你有了表4中信息就會(huì)很聰明的去特別優(yōu)化響應(yīng)時(shí)間在0.01秒到0.1秒之間的那47,444個(gè)調(diào)用。

10. 風(fēng)險(xiǎn)最小化
前面的章節(jié)我提到過(guò),當(dāng)修復(fù)一個(gè)任務(wù)性能問(wèn)題時(shí)可能破壞另一個(gè)任務(wù)的性能,讓我想起了一件曾經(jīng)在丹麥發(fā)生的事。 這個(gè)故事很短:

場(chǎng)景:
在丹麥的巴勒魯普自治市(Måløv)的一張橡木餐桌前,大約10個(gè)人圍坐一起,在用筆記本工作和相互交流。
Carry:伙計(jì)們我快熱死了,你們不介意我打開(kāi)窗戶放點(diǎn)冷空氣進(jìn)來(lái)吧?
Carel-jan: 為什么你不把你的厚毛衣脫了呢?
完。

在這里, 有個(gè)樂(lè)觀的人都知道的一般性原則在發(fā)揮效力:

“當(dāng)大家都很舒適除了你以外,那么你首先應(yīng)該確保影響自己的東西是否正常, 否則你可能去搞亂一些全局的東西導(dǎo)致每一個(gè)人都受影響”

正是這個(gè)原則,當(dāng)因?yàn)閹讉€(gè)寫的很爛的java應(yīng)用程序有人建議我去調(diào)整oracle的網(wǎng)絡(luò)包大小時(shí)讓我感到很害怕。 這些很爛的程序產(chǎn)生了很多不必要的數(shù)據(jù)庫(kù)調(diào)用,自然也產(chǎn)生了很多不必要的網(wǎng)絡(luò)等待。 當(dāng)其他一切正常除了這幾個(gè)爛程序,那么最安全的做法是將調(diào)整的范圍本地化,只需要去調(diào)整這幾個(gè)爛程序就好了。

11. 效率
即便依賴此系統(tǒng)進(jìn)行工作的所有人都很痛苦,你依然需要首先專注于業(yè)務(wù)上最優(yōu)先需要修正的程序部分。 讓程序工作的盡可能的高效是一個(gè)很好的切入點(diǎn)。 在不增加容量,不犧牲必須的業(yè)務(wù)功能的前提下,效率是能夠節(jié)省下來(lái)的任務(wù)總執(zhí)行時(shí)間的倒數(shù)。
換句話說(shuō),效率就是從反面對(duì)浪費(fèi)進(jìn)行的度量。 下面是一些經(jīng)常發(fā)生在數(shù)據(jù)庫(kù)應(yīng)用中浪費(fèi)的例子。

例: 一個(gè)中間層程序?yàn)椴迦霐?shù)據(jù)庫(kù)的每條記錄創(chuàng)建了一條獨(dú)立的SQL語(yǔ)句。 它執(zhí)行了10,000次數(shù)據(jù)庫(kù)預(yù)編譯語(yǔ)句調(diào)用,導(dǎo)致了10,000次網(wǎng)絡(luò)I/O調(diào)用。 其實(shí)它可以只使用一條預(yù)編譯語(yǔ)句,從而節(jié)省9,999次網(wǎng)絡(luò)I/O調(diào)用。

例: 一個(gè)SQL語(yǔ)句訪問(wèn)數(shù)據(jù)庫(kù)緩沖區(qū)緩存7,428,322次獲得了698行的結(jié)果集。 使用一個(gè)額外的過(guò)濾預(yù)測(cè),只返回了終端用戶真正想要看見(jiàn)的7行結(jié)果,只需訪問(wèn)緩沖區(qū)緩存52次。

確實(shí)如果一個(gè)系統(tǒng)存在一些全局性的問(wèn)題(不良索引、錯(cuò)誤參數(shù)、弱弱的硬件配置)導(dǎo)致了一大片任務(wù)執(zhí)行的低效率,你應(yīng)當(dāng)修正它。 但不要嘗試調(diào)優(yōu)系統(tǒng)去滿足低效的程序。 有很多辦法來(lái)調(diào)優(yōu)低效的程序本身。 即使這個(gè)程序是商業(yè)的現(xiàn)成的軟件,那么和你的軟件供應(yīng)商一起去優(yōu)化程序本身比你去優(yōu)化系統(tǒng)讓其盡可能的高效從長(zhǎng)期來(lái)說(shuō)會(huì)更受益。

讓程序變的更高效會(huì)讓工作在這個(gè)系統(tǒng)上的每一個(gè)人都受益巨大。 很容易看到浪費(fèi)的減少對(duì)任務(wù)響應(yīng)時(shí)間的貢獻(xiàn)。 但依然有很多人不明白為什么提升這部分程序的性能會(huì)導(dǎo)致一種副作用,讓看起來(lái)完全不相關(guān)的另一個(gè)程序性能變差。 其實(shí)這是系統(tǒng)負(fù)載在作祟。

12. 負(fù)載
負(fù)載是并發(fā)任務(wù)執(zhí)行時(shí)引發(fā)的資源競(jìng)爭(zhēng)。 負(fù)載正是我們?yōu)槭裁床荒茉谛阅軠y(cè)試中捕捉到所有性能問(wèn)題的原因,而這些問(wèn)題以后會(huì)在生產(chǎn)環(huán)境發(fā)生。 負(fù)載的一個(gè)測(cè)量指標(biāo)是使用率。 使用率反應(yīng)了資源按時(shí)間分片的使用情況。 當(dāng)某個(gè)資源使用率上升時(shí),那么請(qǐng)求該資源服務(wù)的用戶就不等不經(jīng)歷更長(zhǎng)的響應(yīng)時(shí)間。 任何一個(gè)在城市的高峰期開(kāi)車的人都經(jīng)歷過(guò)類似現(xiàn)象。 當(dāng)交通變的嚴(yán)重?fù)矶聲r(shí),你不得不在收費(fèi)站前等待更長(zhǎng)的時(shí)間。

你的汽車在開(kāi)闊的道路上能開(kāi)上每小時(shí)60英里,但在擁堵的路上只能以每小時(shí)30英里的速度行駛,而軟件不會(huì)像汽車這樣真的變慢。 軟件按照固定的同樣的速度執(zhí)行,每個(gè)時(shí)鐘周期總是執(zhí)行同樣數(shù)量的指令,但響應(yīng)時(shí)間會(huì)隨著系統(tǒng)資源變的繁忙而嚴(yán)重退化。

負(fù)載上升系統(tǒng)變慢的原因有兩個(gè):隊(duì)列延遲和相關(guān)性延遲。 下面我會(huì)進(jìn)一步講述。

13. 隊(duì)列延遲
負(fù)載和響應(yīng)時(shí)間之間在數(shù)學(xué)上的相關(guān)性大家都很熟悉了。 一個(gè)叫做”M/M/m”的數(shù)學(xué)模型將響應(yīng)時(shí)間和負(fù)載關(guān)聯(lián)起來(lái)應(yīng)用于一些特定的需求場(chǎng)景下。 M/M/m模型的一個(gè)假設(shè)前提是你的系統(tǒng)模型擁有理論上的完美擴(kuò)展性。 這個(gè)假設(shè)非常類似于我們?cè)诔跫?jí)物理學(xué)課程中經(jīng)常提到的光滑表面(無(wú)摩擦力)假設(shè)。

雖然M/M/m模型假設(shè)的條件有些不現(xiàn)實(shí),如完美的可擴(kuò)展性,但從中依然可以學(xué)到很多。 圖4使用M/M/m模型展示了負(fù)載和響應(yīng)時(shí)間之間的關(guān)系。
從圖4,你從數(shù)學(xué)的角度看到了系統(tǒng)在不同負(fù)載條件下給你的感受。 低負(fù)載下的響應(yīng)時(shí)間和無(wú)負(fù)載基本一樣。 當(dāng)負(fù)載上升時(shí),你能感受到響應(yīng)時(shí)間有一個(gè)輕微、平緩的退化。 這種平緩的變化不會(huì)造成什么麻煩,但隨著負(fù)載繼續(xù)上升響應(yīng)時(shí)間開(kāi)始以一種急劇的方式退化,這可要造成大麻煩了。

就是這樣一個(gè)等式:R = S + Q
服務(wù)時(shí)間(S)就是任務(wù)的執(zhí)行時(shí)間。
隊(duì)列延遲(Q)就是任務(wù)在隊(duì)列中等待機(jī)會(huì)獲得消費(fèi)某個(gè)資源的時(shí)間。

所以當(dāng)你在 Taco Tico(美國(guó)和墨西哥邊境的快餐連鎖)訂餐時(shí),你的訂單響應(yīng)時(shí)間(R)就包括了等待服務(wù)員來(lái)餐桌邊接收訂單的等待時(shí)間,這就是隊(duì)列延遲等待(Q),而服務(wù)時(shí)間(S)就是從訂單交到服務(wù)員時(shí)到食物送到你手上的等待時(shí)間。 同樣,任務(wù)的響應(yīng)時(shí)間在有負(fù)載和無(wú)負(fù)載的系統(tǒng)之間是有差別的。

14. 拐點(diǎn)
提及性能,你想要達(dá)到兩個(gè)目標(biāo)
1. 你想要獲得最快的響應(yīng)時(shí)間:你不想任務(wù)的完成需要太長(zhǎng)的時(shí)間。
2. 你想要獲得最大的吞吐量:同一時(shí)間能支持更多人執(zhí)行他們的任務(wù)。
不幸的是這兩個(gè)目標(biāo)是相互矛盾的。 優(yōu)化達(dá)到第一個(gè)目標(biāo)需要你最小化系統(tǒng)的負(fù)載,而達(dá)到第二個(gè)目標(biāo)則要最大化系統(tǒng)負(fù)載,二者不可兼得。 在這兩者之間的某個(gè)負(fù)載值就是系統(tǒng)的最優(yōu)負(fù)載。

處于最優(yōu)負(fù)載平衡點(diǎn)的資源使用率的值,我稱其為“拐點(diǎn)”。 系統(tǒng)中某種資源達(dá)到“拐點(diǎn)”后,那么吞吐量被最大化了而對(duì)響應(yīng)時(shí)間只有很小的負(fù)面影響。 從數(shù)學(xué)上來(lái)講,“拐點(diǎn)”就是響應(yīng)時(shí)間除以資源利用率所得結(jié)果最小的值。 “拐點(diǎn)”有個(gè)很好的屬性,就是位于從原點(diǎn)畫(huà)一條直線正好與響應(yīng)時(shí)間曲線相切的位置。 在一個(gè)仔細(xì)繪制的M/M/m圖中,你能很容易的利用這個(gè)屬性找到“拐點(diǎn)”,如下圖5所示。

關(guān)于M/M/m模型“拐點(diǎn)”的另一個(gè)很好的屬性是你只需要知道一個(gè)參數(shù)就可以計(jì)算出它。 這個(gè)參數(shù)就是系統(tǒng)中并行的、相同的和獨(dú)立的服務(wù)通道數(shù)。 服務(wù)通道是一種資源,它們共享一個(gè)隊(duì)列,其他資源像收費(fèi)站或者SMP(Symmetric multiprocessing 對(duì)稱多處理)結(jié)構(gòu)的計(jì)算機(jī)中的CPU都是類似的概念。

在M/M/m模型中,斜體小寫的m表示系統(tǒng)建模時(shí)服務(wù)通道數(shù)。 對(duì)任意一個(gè)系統(tǒng)來(lái)說(shuō),計(jì)算“拐點(diǎn)”都是很困難的,好在我已經(jīng)給你計(jì)算出來(lái)了(見(jiàn)表5)。 表5中列出了一些常見(jiàn)的服務(wù)通道數(shù)的“拐點(diǎn)”值。(此時(shí)你也許想知道在M/M/m隊(duì)列模型中另外兩個(gè)M代表什么。它們與進(jìn)入請(qǐng)求時(shí)間和服務(wù)時(shí)間的隨機(jī)性假設(shè)有關(guān)。 更多請(qǐng)參考Kendall’s Notation或進(jìn)一步參考Optimizing Oracle Performance_11)

為何“拐點(diǎn)”如此重要? 對(duì)于那些請(qǐng)求隨機(jī)到達(dá)的系統(tǒng),如果資源負(fù)載持續(xù)超過(guò)“拐點(diǎn)”,那么響應(yīng)時(shí)間和吞吐會(huì)因?yàn)樨?fù)載的輕微變化而嚴(yán)重波動(dòng)。 所以:

對(duì)于請(qǐng)求隨機(jī)到達(dá)的系統(tǒng)而言,保持負(fù)載低于拐點(diǎn)是至關(guān)重要的。 

15. 拐點(diǎn)的相關(guān)性
那么“拐點(diǎn)”的概念是不是真的如此重要呢? 畢竟,我曾經(jīng)告訴過(guò)你M/M/m模型建立在一個(gè)理想的烏托邦理念之上,那就是系統(tǒng)擁有完美的可擴(kuò)展性。 我知道你正在想什么:你想的都是錯(cuò)的。

M/M/m模型告訴我們,即便你的系統(tǒng)擁有完美的可擴(kuò)展性,你依然會(huì)遭遇巨大的性能問(wèn)題只要系統(tǒng)的平均負(fù)載超過(guò)了圖表10中給出的拐點(diǎn)。 那么現(xiàn)實(shí)中你的系統(tǒng)不可能比M/M/m假設(shè)的理論系統(tǒng)更完美。 所以,你的系統(tǒng)的真實(shí)“拐點(diǎn)”會(huì)比我在表5中給出的更小。(我在這里對(duì)拐點(diǎn)值使用了復(fù)數(shù)形式,因?yàn)槟憧梢曰贑PU來(lái)建立拐點(diǎn)模型,同時(shí)也可以基于你的磁盤、網(wǎng)絡(luò)I/O等等)

再次說(shuō)明:
1. 你的系統(tǒng)中的每一項(xiàng)資源都有一個(gè)“拐點(diǎn)”。
2. 你的系統(tǒng)“拐點(diǎn)”都是小于或等于表5中給出的理論值,你的系統(tǒng)擴(kuò)展的完美性越差,“拐點(diǎn)”越小。
3. 對(duì)于請(qǐng)求隨機(jī)到達(dá)的系統(tǒng),如果資源負(fù)載持續(xù)超過(guò)“拐點(diǎn)”,你將遭遇性能問(wèn)題。
所以,保持負(fù)載低于拐點(diǎn)是至關(guān)重要的。

16. 容量規(guī)劃
理解了“拐點(diǎn)”可以減少容量規(guī)劃的復(fù)雜性,可以這樣來(lái)規(guī)劃:
1. 某項(xiàng)資源的容量就是在高峰期能輕松的運(yùn)行你的任務(wù)而資源使用率不會(huì)超過(guò)“拐點(diǎn)”。
2. 保持資源利用率低于“拐點(diǎn)”,那么系統(tǒng)表現(xiàn)就基本不會(huì)給你帶來(lái)大的“驚喜”。
3. 但是,如果你系統(tǒng)中任何一項(xiàng)資源超出了它們的“拐點(diǎn)”,你就會(huì)遭遇性能問(wèn)題,無(wú)論你是否意識(shí)到。
4. 如果你遭遇性能問(wèn)題,不要糾結(jié)于數(shù)學(xué)模型上,要修正這些問(wèn)題要么重新安排下負(fù)載分配,要么減少負(fù)載,要么增加容量。
這就是將性能管理過(guò)程和容量規(guī)劃結(jié)合起來(lái)的辦法。

17. 隨機(jī)到達(dá)
你可能已經(jīng)注意到了,我在前文經(jīng)常提及“隨機(jī)到達(dá)”這個(gè)說(shuō)法,為什么它如此重要? 現(xiàn)在一些系統(tǒng)擁有的特征你可能不會(huì)具備,如:完全確定的作業(yè)調(diào)度。 另外一些系統(tǒng)被配置為接受任務(wù)的方式像是機(jī)器人模式,如每秒接受一個(gè)任務(wù),十分固定,當(dāng)然現(xiàn)在這些系統(tǒng)很少見(jiàn)了。 我這里說(shuō)的一秒一個(gè)任務(wù),并不是說(shuō)平均一秒一個(gè)任務(wù),例如第一秒2個(gè)任務(wù),而下一秒0個(gè)任務(wù)。 我指的是均勻的一秒來(lái)一個(gè)任務(wù),類似汽車工廠組裝線上機(jī)器人的工作模式。

如果任務(wù)到達(dá)系統(tǒng)是完全確定的,就是說(shuō)你完全能預(yù)知下一個(gè)請(qǐng)求什么時(shí)候到達(dá),那么讓資源的使用率超過(guò)“拐點(diǎn)”必然不會(huì)引發(fā)性能問(wèn)題。 對(duì)于一個(gè)任務(wù)到達(dá)很確定的系統(tǒng),那么你的目標(biāo)應(yīng)該是將資源利用到100%,而不是讓它們排隊(duì)等待。 拐點(diǎn)對(duì)于隨機(jī)到達(dá)的系統(tǒng)如此重要的原因是,隨機(jī)任務(wù)請(qǐng)求往往會(huì)聚集并引發(fā)短暫的資源使用脈沖式上升。 這些脈沖式上升需要足夠的剩余容量來(lái)消化它們,所以當(dāng)脈沖發(fā)生時(shí)可能就會(huì)引發(fā)隊(duì)列延遲并導(dǎo)致響應(yīng)時(shí)間的明顯起伏。

短暫的脈沖并導(dǎo)致資源使用率超過(guò)“拐點(diǎn)”也還好,只要不要持續(xù)達(dá)到數(shù)秒時(shí)間。 這個(gè)數(shù)秒到底應(yīng)該是多少秒呢? 我相信(當(dāng)然我沒(méi)試過(guò)去證明)這個(gè)時(shí)間最好不要超過(guò)8秒。(來(lái)自著名的互聯(lián)網(wǎng)8秒原則) 如果你無(wú)法滿足在特定百分比下響應(yīng)時(shí)間和吞吐量對(duì)用戶的承諾,那么很顯然系統(tǒng)脈沖上升持續(xù)時(shí)間太長(zhǎng)了。

18. 相關(guān)性延遲
你的系統(tǒng)肯定不具備理論上的完美擴(kuò)展性。 盡管我從沒(méi)分析過(guò)你的系統(tǒng),但我敢打賭無(wú)論你的系統(tǒng)是什么樣的也不具備“M/M/m”理論模型假設(shè)的完美擴(kuò)展性。 那么相關(guān)性延遲正是你的建模不可能完美的原因。 執(zhí)行任務(wù)時(shí)花在對(duì)共享資源訪問(wèn)的協(xié)商和通信的時(shí)間就是相關(guān)性延遲。 和響應(yīng)時(shí)間、服務(wù)時(shí)間、隊(duì)列延遲一樣,相關(guān)性延遲也可以在任務(wù)的執(zhí)行中被測(cè)量,例如每點(diǎn)擊秒數(shù)。

這里我并不想描述預(yù)測(cè)相關(guān)性延遲的數(shù)學(xué)模型。 但如果你分析過(guò)你的任務(wù)執(zhí)行情況,你可以了解什么時(shí)候相關(guān)性延遲會(huì)發(fā)生。 在oracle中,一些同步的事件正是相關(guān)性延遲的例子:

入隊(duì)列(enqueue)
緩沖忙等待(buffer busy waits)
閂鎖釋放(latch free)

你不能使用M/M/m來(lái)對(duì)相關(guān)性延遲進(jìn)行建模。 因?yàn)镸/M/m模型假設(shè)了你的m個(gè)服務(wù)通道是完全并行的、等同的和獨(dú)立的。 這個(gè)模型假設(shè)在一個(gè)先進(jìn)先出(FIFO)隊(duì)列中,只要你等待的時(shí)間足夠長(zhǎng),在你之前的請(qǐng)求已出隊(duì)列并得到服務(wù),那么最終你也會(huì)得到服務(wù)。 但是相關(guān)性延遲不是這樣工作的。

例: 假設(shè)在一個(gè)HTML數(shù)據(jù)表單上,有個(gè)按鈕是“更新”,點(diǎn)擊它會(huì)執(zhí)行一條SQL更新語(yǔ)句。 另外一個(gè)按鈕是“保存”,點(diǎn)擊它執(zhí)行事務(wù)提交將剛才的更新保存下來(lái)。 如果一個(gè)應(yīng)用是這樣做的,我可以保證它的性能是非常糟糕的。 這是因?yàn)檫@樣一種設(shè)計(jì),讓下面的場(chǎng)景成為可能的,實(shí)際上這也是必然可能的。 一個(gè)用戶先點(diǎn)擊了“更新”,發(fā)現(xiàn)到了午餐時(shí)間,然后就去吃飯了,過(guò)了兩小時(shí)下午回來(lái)再點(diǎn)擊保存。

對(duì)于想要更新同一行的其他任務(wù)來(lái)說(shuō),這是一個(gè)災(zāi)難。 其他任務(wù)不得不等待獲取行鎖,更糟的情況下甚至是頁(yè)鎖。 直到原來(lái)鎖定的用戶想起繼續(xù)點(diǎn)擊“保存”。 或者DBA來(lái)殺掉原來(lái)鎖定用戶的會(huì)話,這樣的話當(dāng)然又會(huì)給原用戶造成錯(cuò)覺(jué),他以為他更新了一行實(shí)際卻沒(méi)有,這可糟透了。

在這個(gè)例子中,不管系統(tǒng)繁忙與否,一個(gè)任務(wù)就在那無(wú)所事事的等待鎖的釋放。 它依賴了系統(tǒng)資源利用率之外的一些隨機(jī)性因素。 這就是為什么你不能使用M/M/m模型來(lái)對(duì)其進(jìn)行建模。 這也是為什么在一個(gè)單元測(cè)試環(huán)境下的性能測(cè)試結(jié)果不足以用來(lái)決策是否應(yīng)該在生產(chǎn)環(huán)境添加一些新的代碼。

19. 性能測(cè)試
我們談到的隊(duì)列延遲、相關(guān)性延遲引發(fā)了一個(gè)很困難的問(wèn)題。 你如何對(duì)一個(gè)新的應(yīng)用進(jìn)行足夠的測(cè)試,讓你信心滿滿的認(rèn)為它不為因?yàn)樾阅軉?wèn)題而對(duì)你的生產(chǎn)程序造成破壞。 你可以去建模,也可以去測(cè)試。 但是,為所有你可以預(yù)見(jiàn)的生產(chǎn)問(wèn)題去建立模型和測(cè)試是極其困難的,在你真正遭遇這些問(wèn)題之前。

因此,一些人看到了這樣窘境,因此申辯說(shuō)那么就干脆別測(cè)試了。
千萬(wàn)別被這樣的心態(tài)所困擾。
下面幾點(diǎn)是很確定的:
1. 在程序進(jìn)入生產(chǎn)環(huán)境之前,如果你嘗試去發(fā)現(xiàn)一些問(wèn)題你肯定會(huì)比那些完全不去做的找到更多的問(wèn)題。
2. 在預(yù)發(fā)布的測(cè)試中,你不可能發(fā)現(xiàn)所有的問(wèn)題。
3. 所以你需要一些可靠并有效的方法來(lái)解決這些在預(yù)發(fā)布測(cè)試中漏掉的問(wèn)題。

在完全不測(cè)試和完整的生產(chǎn)環(huán)境模擬測(cè)試之間,存在一個(gè)適度測(cè)試量的平衡點(diǎn)。 當(dāng)然對(duì)于一家飛機(jī)制造商來(lái)說(shuō),適度測(cè)試量肯定多于一家銷售棒球帽的公司。 但千萬(wàn)別完全跳過(guò)性能測(cè)試。 至少,當(dāng)你在生產(chǎn)環(huán)境遭遇不可避免的性能問(wèn)題時(shí),一份性能測(cè)試計(jì)劃將使你成為一名更稱職的診斷專家(更清晰的思考者)。

20. 測(cè)量
人們能感知到的就是吞吐量和響應(yīng)時(shí)間。 吞吐量很容易測(cè)量,相對(duì)來(lái)說(shuō)測(cè)量響應(yīng)時(shí)間要稍微困難些。(還記得吧,吞吐量和響應(yīng)時(shí)間可不是簡(jiǎn)單的倒數(shù)關(guān)系) 用個(gè)秒表來(lái)計(jì)時(shí)終端用戶的行為并不困難,但你不會(huì)從中得到你真正想要的關(guān)于為什么響應(yīng)時(shí)間如此之大的細(xì)節(jié)。

不幸的是,人們總是測(cè)量他們?nèi)菀诇y(cè)量的,而不是他們應(yīng)當(dāng)測(cè)量的。 當(dāng)我們需要測(cè)量的東西不容易測(cè)量時(shí),我們就把注意力轉(zhuǎn)移到那些容易得到測(cè)量數(shù)據(jù)上了。 這是個(gè)錯(cuò)誤。 那些并不是你真正需要的測(cè)量,但看起來(lái)似乎和你真正需要的有些相關(guān)又容易去執(zhí)行的測(cè)量,我們稱之為“替代指標(biāo)”。 一些“代指標(biāo)”例子包括像子程序調(diào)用計(jì)數(shù)和子程序執(zhí)行耗時(shí)的采樣數(shù)據(jù)。 對(duì)于“替代指標(biāo)”,很遺憾在我的母語(yǔ)中沒(méi)有更好的語(yǔ)句來(lái)表達(dá)我的想法,但有一個(gè)大家都熟悉的現(xiàn)代表達(dá)方式:

“替代指標(biāo)真是惡心(Surrogate measures suck.)”

不幸的是,”惡心“在這里并不表示它“沒(méi)用”。 要是替代指標(biāo)真的沒(méi)用就好了,那就沒(méi)人會(huì)使用它們了。 問(wèn)題就在于替代指標(biāo)有時(shí)是有用的,這讓使用替代指標(biāo)的人相信它們總是有用,但實(shí)際并不是這樣。
替代指標(biāo)有兩個(gè)嚴(yán)重的問(wèn)題:
1. 它們可能在系統(tǒng)不正常時(shí)告訴你系統(tǒng)一切正常,這在統(tǒng)計(jì)學(xué)上叫做第一型錯(cuò)誤,假陽(yáng)性。
2. 它們也可能在系統(tǒng)正常時(shí)告訴你系統(tǒng)出問(wèn)題了,這在統(tǒng)計(jì)學(xué)上叫做第二型錯(cuò)誤,假陰性。
這兩類錯(cuò)誤浪費(fèi)了人們?cè)S多的時(shí)間。

當(dāng)你去評(píng)測(cè)一個(gè)真實(shí)系統(tǒng)方方面面,你能否取得成功在于你能從那個(gè)系統(tǒng)中獲得多少有效的測(cè)量數(shù)據(jù)。 我曾有幸在oracle的市場(chǎng)部門工作過(guò),那時(shí)許多軟件供應(yīng)商圍繞著我們積極的參與,這才使得正確的測(cè)量系統(tǒng)成為可能。 讓軟件開(kāi)發(fā)者使用oracle提供的工具是另外一回事了,至少我們的產(chǎn)品中具備這樣的能力(記錄有效的測(cè)量數(shù)據(jù))。

21. 性能是一項(xiàng)功能特性
性能是軟件程序的一項(xiàng)功能功能特性,就像在你的bug跟蹤系統(tǒng)中很方便的將“Case 1234”這樣一個(gè)字符串自動(dòng)鏈接到編號(hào)1234的bug案例上。 性能像所有其他軟件功能一樣,不是湊巧得到的。 你需要去設(shè)計(jì)和構(gòu)建它。 要想獲得好的性能,你不得不去仔細(xì)的思考、研究、學(xué)習(xí),寫出額外的代碼來(lái)測(cè)試和支持它。

盡管如此,像所有其他功能特性一樣,在項(xiàng)目初期你還在調(diào)研、設(shè)計(jì)和編寫代碼時(shí)你不可能知道性能到底會(huì)怎樣。 對(duì)大多數(shù)應(yīng)用(可能是絕大多數(shù),這個(gè)說(shuō)法可能有爭(zhēng)議)而言性能都是未知的,直到它們投入實(shí)際使用階段。
那么留給你的問(wèn)題就是:

“因?yàn)樵谏暇€前你不可能知道你的應(yīng)用性能表現(xiàn)到底怎樣,因此你需要在編寫應(yīng)用時(shí)考慮怎樣很容易的在生產(chǎn)環(huán)境修復(fù)性能問(wèn)題。”

正如大衛(wèi)·加文(David Garvin)告訴我們的,容易測(cè)量的東西也更容易管理(來(lái)自《建立一個(gè)學(xué)習(xí)型組織》1993年發(fā)表于《哈佛商業(yè)評(píng)論》) 那么要寫一個(gè)在生產(chǎn)環(huán)境容易修復(fù)問(wèn)題的應(yīng)用首先要做的就是要容易在生產(chǎn)環(huán)境測(cè)量。 大多數(shù)時(shí)候,當(dāng)我提到生產(chǎn)環(huán)境的性能測(cè)量時(shí)人們會(huì)陷入一種焦慮狀態(tài),他們很擔(dān)心性能測(cè)量帶來(lái)的入侵效應(yīng)。 他們立刻對(duì)采集哪些數(shù)據(jù)做出了妥協(xié),只留下那些”替代指標(biāo)“(更容易采集的)在數(shù)據(jù)采集表上。 擁有額外數(shù)據(jù)采集代碼的軟件會(huì)變的比沒(méi)有這些代碼的更慢么?

我喜歡湯姆·凱特(Tom Kyte)以前對(duì)這個(gè)問(wèn)題的回答。 他估計(jì)額外的性能度量代碼給oracle帶來(lái)不超過(guò)10%性能損失。 他接著向那些氣惱的提問(wèn)者作出解釋,正是因?yàn)閺倪@些性能測(cè)量代碼獲取的數(shù)據(jù)讓oracle公司進(jìn)一步將產(chǎn)品性能改進(jìn)提升了不止10%,這超出了性能測(cè)量代碼本身引發(fā)的開(kāi)銷。

我認(rèn)為很多軟件供應(yīng)商他們通?;ㄙM(fèi)了太多時(shí)間來(lái)優(yōu)化他們的性能測(cè)量代碼路徑使其更高效,而不是首先搞清楚怎么讓這些代碼有效果。
高德鈉(Donald Knuth)曾在1974說(shuō)過(guò)的一句話印證了這個(gè)觀點(diǎn):

“過(guò)早優(yōu)化是一切罪惡的根源”。

軟件設(shè)計(jì)者將性能測(cè)量代碼整合進(jìn)他們的產(chǎn)品中更有可能創(chuàng)建一個(gè)高性能的應(yīng)用,更重要的是這個(gè)應(yīng)用會(huì)不斷變的更快。

22. 致謝(略)

23. 關(guān)于作者
Cary Millsap 是一位在oracle全球社區(qū)著名的演講者、教育者、顧問(wèn)和作者。 他目前是一家致力于軟件性能優(yōu)化方面的小公司的創(chuàng)建者和CEO。
(部分內(nèi)容省略)

24. 尾聲:關(guān)于“拐點(diǎn)”的公開(kāi)辯論
在本文的14到16節(jié),我描述了“拐點(diǎn)”的性能曲線、它們的相關(guān)性和應(yīng)用。 但是,在20年前有一場(chǎng)關(guān)于是否值得定義一個(gè)“拐點(diǎn)”概念的公開(kāi)辯論。

歷史上的一個(gè)重要的觀點(diǎn)認(rèn)為我所描述的“拐點(diǎn)”并不是真正有意義的。 在1988年,斯蒂芬·薩姆森(stephen samson)爭(zhēng)論說(shuō)至少在M/M/1的排隊(duì)系統(tǒng)的性能曲線中并不存在“拐點(diǎn)”。 他寫道:“選擇一個(gè)具備指導(dǎo)意義的數(shù)字并不容易,經(jīng)驗(yàn)法則還是最適用的。在大多數(shù)情況下都不存在拐點(diǎn),無(wú)論你多么希望找到一個(gè)。”

1999年,溫水煮青蛙的故事啟發(fā)了我。 這個(gè)故事是這樣的說(shuō)的,當(dāng)你把一只青蛙扔進(jìn)煮沸的開(kāi)水中,它會(huì)立刻跳出來(lái)。 但假如你先把它放在冷水中并慢慢的加熱水溫,青蛙會(huì)安靜的呆在水里直到被煮熟了。 對(duì)于資源使用率,它就像是沸水,有一個(gè)清晰的“死亡區(qū)間”,在這個(gè)區(qū)間值內(nèi),對(duì)于隨機(jī)到達(dá)的請(qǐng)求你的系統(tǒng)將不堪重負(fù)。 那么“死亡區(qū)間”的邊界在哪里?如果你嘗試用程序來(lái)自動(dòng)管理資源使用率,你就必須知道這個(gè)值。

最近,我的朋友尼爾·岡瑟(Neil Gunther)跟我有一場(chǎng)私下的辯論。 首先,他認(rèn)為“拐點(diǎn)”這個(gè)術(shù)語(yǔ)使用在這里是完全錯(cuò)誤的,因?yàn)樵跊](méi)有函數(shù)連續(xù)性中斷的前提下使用拐點(diǎn)是錯(cuò)誤的。 其次,他認(rèn)為對(duì)于M/M/1系統(tǒng)的拐點(diǎn)在0.5是過(guò)于浪費(fèi)了,你應(yīng)當(dāng)更多的利用好系統(tǒng)資源,它應(yīng)高于0.5的資源利用率。 最后,他認(rèn)為你對(duì)使用率的明確定義取決于實(shí)際的平均響應(yīng)時(shí)間相對(duì)你能忍受的平均響應(yīng)時(shí)間實(shí)際超出了多少。 因此,岡瑟認(rèn)為任何有用的使用率閾值的定義都來(lái)源于詢問(wèn)人們自身的偏好,而非來(lái)自于數(shù)學(xué)。(圖A)

話雖如此,我也不知道該如何確切的定義“過(guò)大”這個(gè)詞。 像響應(yīng)時(shí)間波動(dòng)的忍耐度,不同的人有不同的底線。 或許有一個(gè)起伏忍耐的因子適用于所有人。 例如,Apdex standard(Application Performance Index)假設(shè)了響應(yīng)時(shí)間F是T的4倍就會(huì)讓人們的態(tài)度從“滿意”變?yōu)?ldquo;煎熬”。

拐點(diǎn)無(wú)論你怎么去定義或稱呼它,對(duì)于容量規(guī)劃過(guò)程來(lái)說(shuō)都是一個(gè)十分重要的參數(shù),正如我在16節(jié)中描述的。 并且我相信它對(duì)日常的系統(tǒng)負(fù)載管理也是一個(gè)重要參數(shù)。

責(zé)任編輯:周立方 來(lái)源: 聽(tīng)云
相關(guān)推薦

2012-03-05 10:01:43

移動(dòng)開(kāi)發(fā)

2013-08-26 09:55:27

虛擬化私有云服務(wù)

2009-04-18 14:10:10

2013-11-08 10:42:31

Ubuntu 13.1

2013-01-10 10:34:02

2021-10-08 06:53:30

Windows 11操作系統(tǒng)微軟

2012-07-22 15:22:17

加班

2017-12-25 11:09:09

程序員高薪狀態(tài)

2009-07-17 14:02:20

程序員編程效率

2021-08-03 10:40:47

混合云云計(jì)算應(yīng)用程序

2011-05-26 11:13:36

Flex

2010-03-01 10:20:27

Flex

2010-07-28 14:21:43

Flex

2015-03-11 11:23:38

MySQLPHP開(kāi)發(fā)

2012-01-09 09:45:14

PhoneGapPPT

2020-05-27 10:46:49

Kubernetes容器云計(jì)算

2020-05-08 15:30:42

PostgreSQL數(shù)據(jù)庫(kù)數(shù)據(jù)

2022-04-19 07:48:16

JavascriptCSS

2011-06-03 17:59:36

SEO

2011-02-14 14:10:14

PHPWeb
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品爱久久久久久久 | 成人做爰www免费看 午夜精品久久久久久久久久久久 | 中文字幕 国产精品 | 国产高清视频在线观看 | 在线观看亚洲欧美 | 在线观看中文字幕视频 | 久久精品 | 美美女高清毛片视频免费观看 | 亚洲网站在线观看 | 一区二区三区不卡视频 | 国产成人免费在线观看 | 亚洲风情在线观看 | 免费xxxx大片国产在线 | 97在线观看 | 免费久久精品 | 在线一区二区三区 | 18性欧美 | 欧美国产日韩成人 | 成人欧美一区二区三区视频xxx | 在线视频三区 | 欧洲亚洲一区 | 国产高清av免费观看 | 中文字幕日韩在线 | 午夜免费视频 | 免费一级黄 | 亚洲国产成人精 | 欧美日韩中文在线 | 国产亚洲欧美另类一区二区三区 | 97精品视频在线观看 | 99久久夜色精品国产亚洲96 | 欧美精品福利视频 | 国产精品国产精品国产专区不片 | 黄色大全免费看 | 国产精品免费一区二区三区 | 亚洲国产欧美日韩 | 国产高潮好爽受不了了夜色 | a爱视频| 国产在线中文字幕 | 日韩中文视频 | 午夜成人在线视频 | 超碰在线人 |