複製鏈接
請複製以下鏈接發送給好友

性能分析

鎖定
不合標準的應用程序性能會產生軟件或網絡問題。為確保軟件滿足或超過設計的期望值,有必要分析應用程序的性能以發現潛在的問題。這個過程被稱為“性能分析”。它包括檢查應用程序以確保每個組件有效地工作,並根據設計密切注視處理器的使用、網絡和系統服務、存儲和輸入/輸出(I/O)。
中文名
性能分析
環    節
使應用程序的組件可見
影    響
不合標準應用程序會產生軟件問題
結    果
可以診斷潛在的性能問題

性能分析歷史

早在1970年代,IBM System/360及IBM System/370的平台就有性能分析工具,一般是用計時器中斷在固定的時間紀錄程序狀態字(PSW)來偵測程序運行時的“過熱點”(hot spots)。這是早期使用抽樣方式進行性能分析的示例之一。在1974年時,指令集仿真器就允許完整的事件蹤跡,以及其他性能監控的機能。
以性能分析工具為主的UNIX程序分析至少可以回溯到1979年,當時Unix系統有一個基礎工具prof,可以列出每一個函數,也列出此函數總共花了多少時間。1982年時gprof工具延伸此概念,可以列出完整的函數調用圖。
1994年時,迪吉多的Amitabh Srivastava和Alan Eustace提出了描述ATOM的論文。ATOM是一個平台,可以將程序配合其性能分析工具調整,在編譯期間,ATOM會在要分析的程序中加入代碼,而加入的代碼會輸出分析數據,這種修改程序,輸出自身份析數據的技術,稱為邏輯注入。
2004年時.gprof和ATOM論文都出現在前50個最具影響力的編程語言設計和實現會議(PLDI)論文中。 [1] 

性能分析診斷問題

性能分析的一個必不可少的環節是使應用程序的組件可見。當能夠了解組件是如何交互時,就可以診斷潛在的性能問題。傳統上,瞭解分佈式應用程序中組件間的交互一直很困難。而VisualStudioAnalyzer提供了不同的方法來了解交互情況,從而解決了此問題。例如,可在進程間或這些交互的持續時間內瞭解交互情況。當能夠深入瞭解應用程序並發現出現問題的原因時,就可以:
●確保應用程序的行為按設計如期進行。
●通過詳細報告應用程序和網絡響應以及傳遞的時間,顯示應用程序在哪些方面導致大量的處理開銷、文件爭用或磁盤或網絡訪問過度延遲。
●收集全面的分析數據並將其結合用於應用程序進程的端對端視圖和數據涉及的所有設備。 [1] 

性能分析輸出方式分類

一般性能分析器
一般性能分析器(flat profiler)根據函數調用計算平均的函數調用次數,而且不會根據被調用函數或是運行脈絡(context)細分函數調用次數。 [1] 
函數調用圖性能分析器
函數調用圖會顯示函數被調用的次數及頻率,也會列出函數調用鏈(call-chains),有些軟件會列完整的調用鏈,有些不會。 [1] 

性能分析分析方式分類

性能分析器本身也是程序,可以在被分析程序運行時收集相關信息,來分析該程序。根據收集到信息的細微度,以及收集信息的方式,可以分為事件為基礎的性能分析器,或是統計式的性能分析器。有些性能分析器為了收集信息,會中斷程序的運行,因此在時間量測上有一定的分辨率限制。 [2] 
事件為基礎的性能分析器
以下列出的編程語言有事件為基礎的性能分析器:
  • Java:JVMTI(JVM工具接口)API,以前稱為JVMPI(JVM性能分析接口),提供給性能分析器的hook,可以抓到像函數調用、類別加載、卸載、線程的進入及離開等事件。
  • .NET框架:利用性能分析的API,可以連接到像是COM服務器的性能分析代理器(profiling agent)。像Java一様,在運行會提供許多回調函數給代理器,可以捕捉到像是方法JIT/進入/離開,對象創建及其他。特別的是性能分析代理器可以用任意方式改寫目的應用程序的字節碼。
  • Python:Python的性能分析包括profile模塊,以調用函數圖為基礎的hotshot,以及用'sys.setprofile'函數來捕捉像c_{call,return,exception}及python_{call,return,exception}的事件。
  • Ruby:Ruby也用類似Python的性能分析界面。目前有在profile.rb中的一般性能分析器及相關模塊。 [2] 
統計式的性能分析器
有些性能分析器是用取様的方式運作。取様式的性能分析器利用操作系統中斷,在固定時間取様目的程序的程序計數器。取様式的性能分析器在數值上較不精準,但對目的程序運行時間的影響最小,允許目的程序可以在接近全速的速度下運作。
所得到的數據不是精準值,只是統計上的近似值而已。“實際誤差的量一般會大於一個取樣時間.若芋某一數值是取様時間的n倍,其誤差約為n倍取様時間的平方根”
在實務上統計式的性能分析器會比其他的分析方式更能知道目的程序各部分佔的比例,而且相較之下有較少的邊際效應(例如存儲器緩存或是指令解碼的管道線等),由於統計式的性能分析器對程序運行速度的影響較小.因此可以偵測到一些其他方式偵測不到的問題。這種方式可以看出用户模式及可中斷系統模式(例如系統調用)分別佔的時間。
不過由於系統程序需處理中斷,仍然會花一些CPU的運行週期,分散緩存的讀取,而且無法分辨在不可中斷核心模式下的行為。
有些特製的硬件可以克服這類的問題:有些最近MIPS微理器中,JTAG接口有一個PCSAMPLE寄存器,可以用一種無法偵測到的方式來取様程序計數器。
最常用的統計式的性能分析器包括AMD的CodeAnalyst、蘋果公司的Shark(OSX)、Intel的VTune及Parallel Amplifier(Intel Parallel Studio的一部分)。 [2] 
插裝型的性能分析器
有些性能分析可以用插裝(也稱為邏輯注入)的方式處理目的程序,也就是在目的程序中加入額外指令來收集需要的信息。
程序的插裝會影響程序的性能,可能會出現不精確的結果及heisenbug(捉摸不定,不易重現的bug)。插裝一定會對程序運行有些影響,常見的情形是使程序變慢。不過插裝可以特定只針對部分程序,而且可以小心控制以使影響降到最低。其對於特定程序的影響是看插裝放置的位置,以及捕捉蹤跡(trace)的機制。有些處理器有硬件支持可以捕捉蹤跡,插裝可以只佔一個機器語言週期的時間。一般可以從結果中移除插裝的影響。
gprof是一個同時用插裝及取様的性能分析器的例子。插裝用來獲取被調用函數的信息,而實際花的時間則是由取様方式來獲得。
插裝是決定性能分析器可控制程度及時間分辨率的關鍵。以下是一些方式的分類。
  • 手動:是由程序設計者加入指令,在運行時計算相關信息,例如計算事件或是調用像是應用程序響應測試(ARM)標準的API
  • 源代碼層級自動處理:依照插裝政策,利用自動化工具自動在源代碼中加入instrumentation,像Parasoft公司的Insure++
  • 中間語言:在彙編語言或是bytecode中加入針對多種高級語言的instrumentation,,例如OpenPATOpenPAT。
  • 編譯器協助:像gprof和Quantify都是這類的例子,像用gcc -pg ...可以使用gprof,用quantify g++ ...可以使用Quantify。
  • 二進制翻譯:此工具在編譯好的可執行檔中加入instrumentation,例如ATOM。
  • 運行時插裝:代碼直接在運行前修改,工具可以完成的監控及控制程序的運行,例如用PinValgrind、DynamoRIO。
  • 運行時注入:修改程度比運行時插裝要小,代碼在運行時修改,令加入跳躍到協助用函數的指令,例如和DynInst。 [2] 
解釋器式的插裝
  • 解釋器式除錯選項,可以在解釋器處理每個目的指令時,收集性能量度的相關信息。像字節碼、控制表及JIT的解釋器都在目標代碼運行時有完整的控制能力,因此有機會收集到非常全面的數據。 [2] 
hypervisor或仿真器
  • Hypervisor:在hypervisor下運行(一般而言)沒有修改的程序,可以收集相關信息,例如SIMMON工具。
  • 仿真器hypervisor:在指令集模擬器運行(一般而言)沒有修改的程序,可以交互式及選擇性的收集相關信息,例如SIMONOLIVER工具。 [2] 
參考資料
  • 1.    gprof: a Call Graph Execution Profiler // Proceedings of the SIGPLAN '82 Symposium on Compiler Construction, SIGPLAN Notices, Vol. 17, No 6, pp. 120-126; doi:10.1145/800230.806987
  • 2.    Amitabh Srivastava and Alan Eustace, "Atom: A system for building customized program analysis tools", 1994