性能分析

在软件工程中，性能分析（performance analysis，也称为profiling），是以收集程序运行时信息为手段研究程序行为的分析方法，是一種的方法。

性能分析量測像是程式的空間或時間複雜度、、函式呼叫的頻率及執行時間等。性能分析的目的在于决定程序的哪个部分应该被，从而提高程序的速度或者内存使用效率。

性能分析可以由程式的源代碼或是可執行檔進行。一般會使用稱為性能分析工具（profiler）的工具進行。性能分析工具會使用許多不同的技術，可能是以事件為基礎（Event-based）的、統計的、指令導向的、仿真的方法。性能分析工具常用在的过程中。

 性能分析工具 
"若要了解程式行為，程式分析工具非常重要。電腦架構分析師需要這類工具來評估程式在新的系统结构中運作的情形。軟體撰寫者需要這類工具來分析程式，並分析出其中關鍵的區塊。編譯器撰寫者需要這類工具來評估其指令排程或分支預測演算法運作的情形" -- (ATOM, PLDI, '94)

性能分析工具使用广泛的技术手段收集数据，包括硬件中断、、作業系统、CPU内置的，等等。

性能分析输出會是：
 观察到的事件的统计摘要（概要文件）
 摘要配置文件信息通常会根据事件发生的源代码语句进行注释显示，因此测量数据的大小与程序的代码大小成线性关系。
 /* ------------ 源代碼------------------------- 發行次數 */            
 0001             IF X = "A"                     0055
 0002                THEN DO                      
 0003                  ADD 1 to XCOUNT           0032
 0004                ELSE
 0005             IF X = "B"                     0055

 所有事件的记录流（亦称踪迹，英文“trace”）
 事件的记录流则与成线性关系，也就是和运行时长成线性关系。由於資料量过大，有時记录會不切實際。所以，有些程式分析工具可以設定在某特殊條件下才啟動事件踪迹的記錄，在另外特殊條件下結束事件踪迹的記錄。

 对于顺序执行的程序，通常轮廓就足够了。但并行计算程序的性能问题（等待消息或者同步问题）和事件的時間順序有關，因此需要全部的踪迹才能找到问题。

 用hypervisor持續性的互動監控（針對事件連續性或週期性顯示在螢幕上）

 在觀看在執行程式的相關度量時．可在任意時刻啟動或結束事件踪迹的記錄，也可以在一些關鍵的點上暫停非同步的程式來看和其他平行處理程式之間的互動關係。

 历史 
早在1970年代，IBM System/360及的平台就有性能分析工具，一般是用計時器中斷在固定的時間紀錄（PSW）來偵測程式執行時的「過熱點」（hot spots）。這是早期使用抽樣方式進行性能分析的範例之一。在1974年時，就允許完整的事件踪迹，以及其他性能監控的機能。

以性能分析工具為主的UNIX程式分析至少可以回溯到1979年，當時Unix系統有一個基礎工具prof，可以列出每一個函式，也列出此函式總共花了多少時間。1982年時gprof工具延伸此概念，可以列出完整的函式調用圖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。

1994年時，迪吉多的Amitabh Srivastava和Alan Eustace提出了描述ATOM的論文Amitabh Srivastava and Alan Eustace, "Atom: A system for building customized program analysis tools", 1994 (download ) // Proceeding
PLDI '94 Proceedings of the ACM SIGPLAN 1994 conference on Programming language design and implementation. Pages 196 - 205, doi:10.1145/773473.178260。ATOM是一個平台，可以將程式配合其性能分析工具調整，在編譯期間，ATOM會在要分析的程式中加入程式碼，而加入的程式碼會輸出分析資料，這種修改程式，輸出自身分析資料的技術，稱為。

2004年時，gprof和ATOM論文都出現在前50個最具影響力的（PLDI）論文中。

 以输出方式分类 
 一般性能分析器 
一般性能分析器（flat profiler）根據函式呼叫計算平均的函式呼叫次數，而且不會根據被呼叫函數或是執行脈絡（context）細分函式呼叫次數。

 函式調用圖性能分析器 
函式調用圖性能分析器（call graph profiler）會顯示函數被呼叫的次數及頻率，也會列出函式調用鏈（call-chains），有些軟體會列完整的調用鏈，有些不會。

 输入敏感性能分析器 
输入敏感性能分析器（input-sensitive profiler）将性能度量与输入工作负载特征（例如输入大小或输入值）相关联，相比于一般性能分析器或调用图分析器增加了一个维度。它会生成图表描述应用程序性能随其输入的变化情况。

 以分析方式的分類 
性能分析器本身也是程式，可以在被分析程式執行時收集相關資訊，來分析該程式。根據收集到資訊的細微度，以及收集資訊的方式，可以分為事件為基礎的性能分析器，或是統計式的性能分析器。有些性能分析器為了收集資訊，會中斷程式的執行，因此在時間量測上有一定的解析度限制。
事件為基礎的性能分析器
以下列出的程式語言有事件為基礎的性能分析器：
 Java：（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中的一般效能分析器及相關模組。

統計式的性能分析器
有些性能分析器是用取样的方式運作。取様式的性能分析器利用作業系統的中斷，在固定時間取様目的程式的调用栈。取様式的性能分析器在數值上較不精準，但對目的程式執行時間的影響最小，允許目的程式可以在接近全速的速度下運作。

所得到的資料不是精準值，只是統計上的近似值而已。「實際誤差的量一般會大於一個取樣時間。若某一數值是取様時間的n倍，其誤差約為n倍取样時間的平方根。」Statistical Inaccuracy of gprof Output 

在實務上統計式的性能分析器會比其他的分析方式更能知道目的程式各部份占的比例，而且相較之下有較少的邊際效應（例如記憶體快取或是指令解碼的管道線等），由於統計式的性能分析器對程式執行速度的影響較小。因此可以偵測到一些其他方式偵測不到的問題。這種方式可以看出使用者模式及可中斷系統模式（例如系統呼叫）分別佔的時間。

不過由於系統程式需處理中斷，仍然會花一些CPU的執行周期，分散快取的讀取，而且無法分辨在不可中斷核心模式下的行為。

有些特製的硬體可以克服這類的問題：有些最近MIPS微理器中，JTAG介面有一個PCSAMPLE暫存器，可以用一種無法偵測到的方式來取様程式計數器。

最常用的統計式的性能分析器包括AMD的CodeAnalyst、蘋果公司的Shark（OSX）、oprofile（Linux）、Intel的及Parallel Amplifier（的一部份）。

插裝型的性能分析器
有些性能分析可以用（也稱為邏輯注入）的方式處理目的程式，也就是在目的程式中加入額外指令來收集需要的資訊。

程式的插裝會影響程式的效能，可能會出現不精確的結果及 heisenbug（捉摸不定，不易重現的bug）。插裝一定會對程式執行有些影響，常見的情形是使程式變慢。不過插裝可以特定只針對部份程式，而且可以小心控制以使影響降到最低。其對於特定程式的影響是看插裝放置的位置，以及捕捉蹤跡（trace）的機制。有些處理器有硬體支持可以捕捉蹤跡，插裝可以只佔一個机器语言週期的時間。一般可以從結果中移除插裝的影響。

gprof是一個同時用插裝及取様的性能分析器的例子。插裝用來取得被呼叫函式的資訊，而實際花的時間則是由取様方式來獲得。

插裝是決定性能分析器可控制程度及時間解析度的關鍵。以下是一些方式的分類。
 手動：是由程式設計者加入指令，在執行時計算相關資訊，例如計算事件或是呼叫像是（ARM）標準的API。
 源代碼層級自動處理：依照插裝政策，利用自動化工具自動在源代碼中加入instrumentation，像公司的。
 中間語言：在組合語言或是bytecode中加入針對多種高階語言的instrumentation，，例如。
 編譯器協助：像gprof和Quantify都是這類的例子，像用gcc -pg ...可以使用gprof，用quantify g++ ...可以使用Quantify。
 二進位翻譯：此工具在編譯好的可執行檔中加入instrumentation，例如ATOM。
 執行時插裝：代碼直接在執行前修改，工具可以完成的監控及控制程式的執行，例如用、Valgrind、。
 執行時注入：修改程度比執行時插裝要小，代碼在執行時修改，令加入跳躍到協助用函式的指令，例如和。

直譯器式的插裝
 直譯器式除錯選項，可以在直譯器處理每個目的指令時，收集性能量度的相關資訊。像字节码、控制表及JIT的直譯器都在目的碼執行時有完整的控制能力，因此有機會收集到非常全面的資料。

hypervisor/模拟器(simulator)
 Hypervisor：在hypervisor下執行（一般而言）沒有修改的程式，可以收集相關資訊，例如工具。
 模拟器及hypervisor：在執行（一般而言）沒有修改的程式，可以互動式及選擇性的收集相關資訊，例如及工具。

 相關條目 
 演算法效率
 靜態程式分析




 是一套針對現代微處理器的硬體性能計數器的可攜式介面（以函式庫的方式提供）

 （WCET）

 軟體考古學

 參考資料 

 外部連結 
 演示"Using VSTS Performance Tools to Speed Up Your App "，演示者是微軟的程式設計師Ian Huff，演示內容是Visual Studio Team System 2005中的性能分析器
 文章"Need for speed -- Eliminating performance bottlenecks "，是有關利用IBM的Rational Application Developer進行Java應用程式的執行時間分析
 体验报告"Execution time optimisation of an Avionics system"，其中發行現Avionics system中最壞執行時間中的30%是由只佔1.2%的程式所造成

Category:软件优化
Category:分析器