級別: 中級
Goran Begic, 高級 IT 工程師, IBM
Allan Pratt, 首席工程師, IBM
2007 年 5 月 14 日
本文來自於 Rational Edge:本文討論了其他 Rational 最佳實踐中的運行時分析,並概述了其對軟件開發人員、測試人員,和管理人員所帶來的巨大好處。
illustration運行時分析是一種基於觀察系統運行時行為的實踐。它與"靜態分析"不同,靜態分析是指通過觀察源代碼或高級架構分析系統行為;或是分析系統失敗時的"崩潰分析。"
調試是一種經典的運行時分析的例子:設置斷點,一步步地運行系統,並且觀察評估值和變量,通過這些方法瞭解系統運行時所發生的情況。當您調試的過程中,您不會對所有可能發生的事情感興趣,僅僅對真正發生的感興趣。這正是將運行時分析從靜態分析中分離出來的原因。
調試過程是高度互動且有效的,但它受限於所能展示的內容。當您將關注的焦點集中於一行或一個變量時,它很難識別出模式並綜合高級行為。
測試是另一種運行時分析:您通過數據或事件檢驗是否獲得來自系統的正確行為。這種類型的測試是軟件質量的基礎。
傳統的測試僅僅為您展現出這麼多。一個通過了所有測試(獲得正確結果)的系統仍然具有嚴重的質量問題。
這些就是為什麼類似於 IBM Rational PurifyPlus 的運行時分析工具誕生的原因。
什麼是 PurifyPlus?
PurifyPlus 是一種運行時分析工具,它用以在系統運行時監測系統並且報告系統行為的重要內容:
它會使用多少內存?
是否會造成內存泄露?
是否包括內存訪問錯誤?
需要多長時間啓動;瓶頸在哪裏?
什麼是線程運行/睡眠行為?
實際運行的源代碼有多少?
這些關鍵分析特徵都與核心"正確性" 問題無關:"是否能夠運行?"和"是否產生正確結果?" 測試能夠顯示您的系統是否正常工作,利用類似於 PurifyPlus 的運行時分析工具能夠發現所有類型的錯誤。
PurifyPlus 的主要組件有:
內存使用追蹤及內存錯誤檢測
量化的性能分析、代碼流和線程可視化
源代碼覆蓋分析的 PureCoverage
系統開發週期中的運行時分析
交互的開發週期和工程質量方案中重要的自動化構建、測試過程中都會包含運行時分析。
開發與執行過程中的運行時分析
在交互開發過程中,Purify 能夠在新代碼加入工程前報告內存錯誤。開發人員能夠使用 PureCoverage 識別所需新測試的區域。Quantify 能夠在開發早期展現未期望的代碼路徑和瓶頸。
自動化測試過程中的運行時分析
當運行自動化構建測試時,PurifyPlus 能夠使您監測質量並且收集信息以確保工程處於正軌。當您的測試運行於 Purify 且沒有錯誤報告時,您就可以知道系統並不含有內存訪問錯誤和內存泄露。 當所運行的 Quantify 顯示性能滿足目標時,您可以知道系統沒有遇到瓶頸。當 PureCoverage 報告高級別的代碼覆蓋時,您可以知道並沒有引入新的代碼塊,因此不必增加自動測試。
您可以增加利用自動化測試工具(IBM Rational Functional Tester)所獲得的運行時分析數據的質量。自動化的測試能夠在一次疊代中得到更多的測試信息,並且能夠評估所引入的新產品質量效果。如果軟件質量介於兩類連續的組件疊代間,那麼運行時分析數據很容易找出其中的特點或代碼的改變。
用以理解系統的運行時分析
有時,運行時分析並不包括正確性或質量。例如,運行時分析可以幫助理解系統。尤其是,Quantify 能夠展示出調用圖,揭示系統的各個部分如何協調工作,或揭示了非期望的性能下降或交互。
基本的 PurifyPlus 能力
如上所述,IBM Rational PurifyPlus 具有三個主要組件:內存分析的 Purify,性能分析的 Quantify,和代碼覆蓋分析的 PureCoverage。
對於 C/C++ 程序,Purify 自動化的檢測並報告內存泄露和內存訪問錯誤,例如,在內存釋放後使用內存,重複釋放相同區域的內存,或是初始化前從內存讀。所有這些都是潛伏於程序中的軟件質量問題,即使通過了所有測試。這類錯誤可以導致嚴重的生產錯誤。
對於 Java 和 Microsoft .Net 程序("已管理的程序"),Purify 追蹤內存的使用和內存引用,因此,您能夠發現哪裏是內存瓶頸,應在哪裏釋放內存,比對前後圖形以檢測程序中未預料的內存使用 ("泄露")。
Quantify 追蹤程序性能和調用行為,因此您能夠發現執行流並識別出瓶頸。 Quantify 強調了使用 River of Time(tm)特徵的花費最久的代碼路徑。除此之外,Quantify 為您可視化的實現了線程執行行為。
PureCoverage 追蹤代碼覆蓋,因此您可以發現測試與運行時分析工具不能發現的鴻溝。由於 Purify 和 Quantify 僅僅看到了實際運行的代碼,PureCoverage 提供的代碼覆蓋矩陣重點了解正在檢測和更新的質量。
使用 PurifyPlus 的運行時分析的例子
調試的主要目標就是找出缺陷的根本原因並理解程序行為。
運行時分析提供了額外的補充傳統調試不足的能力:
應用執行的可視化。
重要運行時參數的度量,包括內存使用、性能和代碼覆蓋。
用户模式下的錯誤檢測。
運行時行為的文檔。
我們將在下面檢查這些能力。
應用執行的可視化
為理解這一能力,我們將看到以下四個例子。
可視化例子1:代碼覆蓋
使用諸如 Rational® PureCoverage® 的運行時工具(包含於 Rational PurifyPlus 中)提供了各種視圖展現代碼覆蓋信息,其中之一就是 Annotated Source。這一特別的視圖顯示了所檢查的應用的源文件;劃線的顏色指出了執行測試事例之後的狀態:hit、 missed、 dead 或部分 hit。
如圖 1所示,用户能夠看到測試樣例的代碼覆蓋和執行路徑。
Rational PurifyPlus Display of Annotated Source for the C#.NET application in Visual Studio.NET
圖 1: Rational PurifyPlus 在 Visual Studio.NET 中顯示了 C#.NET 樣例
點擊放大
圖 1中的代碼段顯示了第 111 行執行交換陳述時所應用的準確路徑。這一特殊行被標記為部分 hit,因為第 122 行沒有執行。
可視化例子 2:線程
運行時分析工具諸如 Rational Quantify (包含於 Rational PurifyPlus中)提供了線程可視化,它能夠利用標記調試時每個線程的狀態檢測多線程問題。如圖2所示,它允許您在調試時檢測可視化線程的狀態。
Rational Quantify Thread Analysis View in Visual Studio 6
圖 2: Visual Studio 6 中的 Rational Quantify 線程分析視圖
點擊放大
可視化例子 3:調用圖
運行時分析工具還能夠檢測和顯示性能瓶頸。這種方法與傳統方式相比最大的優勢就在於,您可以獲得完美的執行路徑概況,和關於調用數準確信息。如圖 3A 和 3B 所示,Rational Quantify 中的 Call Graph 強調了最大時間消耗執行的路徑的調用鏈;那就是性能弱點。連接方法的粗線表示了調用鏈所花費時間和剩餘應用時間(如果使用 Purify,那就是內存)的比率。
Rational Quantify Call Graph of a Mixed VB.NET and C#.NET Application in Visual Studio.NET
圖 3A: Visual Studio.NET 中 VB.NET 和 C#.NET 應用的混合 Rational Quantify 調用圖
點擊放大
Rational Quantify Call Graph of a C/C++ Application on Solaris
圖 3B: Solaris 中 C/C++ 應用的 Rational Quantify 調用圖
點擊放大
可視化例子 4:內存使用
處理內存泄露的第一步就是要檢測。一種直觀的方式就是可視化全部內存使用並且在測試(PUT)下進行內存快照。這可以在運行中的應用中發現潛在的內存泄露。(在 Rational Purify for Java 和 .NET 管理應用中已經實現)例如,如果對於在服務器端運行的組建內存快照顯示,全部內存性能在客户端增加,之後很可能是組件泄露(見圖 4)。
Overview of Thread Status and Memory Usage in Rational Purify for Windows
圖 4:Rational Purify for Windows 中的線程狀態和內存使用概況
點擊放大
關鍵運行時參數的測量
可見的錯誤檢測僅僅是運行時分析的第一步。我們還需要準確理解運行時所發生的事情。因此,運行時分析應基於針對應用執行的準確的參數測量:
運行時性能
內存使用
代碼覆蓋
我們將再次通過事例理解這一運行時分析的能力。
測量實例 1:函數列表視圖
函數列表視圖是一種典型的運行時分析視圖,它能夠由特殊的運行時分析工具(如 Rational Quantify)創建(見圖 5)。它顯示了表中全部重要的方法和/或應用對象;這樣就允許了開發人員通過分析代碼找出最佳的使用內存的方法,同時可以找出最慢的函數,對象生存時間,等等。
這一視圖提供了關於方法調用總數,方法的時間花費,所選方法的時間花費和內存積聚,及其全部派生的準確信息。
Rational Quantify Function List View for a Visual C++ Application
圖 5:針對 Visual C++ Application 的 Rational Quantify 函數列表視圖
( 點擊放大
測量實例 2: 函數詳細視圖 Function 詳細視圖
運行時分析工具(例如 Rational Quantify)還能夠擴展測量實例 1 中的信息,使它包括了調用方法和派生間的測試數據的分佈信息。如 Function Detail View (圖 6)所示。 這一視圖強調了對於性能或內存熱點(能夠用以幫助檢測準確的性能或內存瓶頸的原因的信息)有意義的調用者和派生。
Figure 6
圖 6:Visual Studio.NET (使用 IBM Rational XDE)中的針對 Visual C#.NET 的 Rational Quantify 函數詳細視圖
點擊放大
測量實例 3:方法覆蓋模塊視圖
正如先前我們所解釋的,在一些實例中--尤其是評估可用測試方法價值時,它對於測量測試過程所覆蓋的代碼比率,或簡單的標記所有未測試的方法是十分有用的。您可以應用諸如 Rational® PureCoverage®的工具,用以產生準確的未測試和廢棄代碼與已測試代碼的信息(圖 7)。
Figure 7
圖 7:Visual Studio.NET (使用 IBM Rational XDE)中對於 C#.NET 和 VB.NET 應用程序的混合方法代碼覆蓋的 Rational PureCoverage 顯示
點擊放大
錯誤檢測:用户模式下的運行時內存崩潰
這是對於純 C/C++ 應用的運行時分析的最高榮耀。運行時分析不但能通過顯示性能、內存、線程和不同視圖中的代碼覆蓋數據檢測錯誤,還能夠在用户模式下準確的指出產生和/或引起錯誤的位置。運行時內存崩潰檢測能夠確保所有平台上的正確函數和高質量的純 C 和 C++ 應用程序。對於運行時內存檢測的 IBM Rational 工具有 Rational Purify 和Rational PurifyPlus。讓我們再來看看一些例子。
錯誤檢測實例 1: Rational Purify 內存錯誤和內存泄露報告
Rational Purify 能夠指出開發人員創建的農村錯誤的準確代碼行。它甚至不需要源文件就可以提供這一信息; Rational Purify 在內存中檢測錯誤,並使用調試信息追蹤回溯找出相應的代碼行(見圖 8)。
Rational Purify Memory Error and Memory Leak Report for a Visual C++ Application
圖 8: 針對 Visual C++ 應用的Rational Purify 內存錯誤和內存泄露報告
點擊放大
在這個例子中,開發人員忘記構建數組變量時考慮終止符。這一錯誤將會導致應用構造的崩潰,而調試構造卻很正常。本例僅僅是運行時分析減少 C/C++開發調試時間的一個例子。
錯誤檢測實例 2:量化標註源
Rational Quantify 具有一種獨一無二的能力,它能夠為用户方法代碼的每一行測量記錄的時間分佈。量化標註源顯示了每行代碼的測量時間,和調用這行所花費的時間。這類信息能夠有助於將性能瓶頸縮小到代碼行級別(圖9)。
Rational Quantify Annotated Source for a Mixed Visual Basic 6 and Visual C++ Application in Visual Studio 6
圖 9: Visual Studio 6 中針對混合的 visual Basic 6 和 Visual C++ 應用的 Rational Quantify 標註源
點擊放大
錯誤檢測實例 3: Purify 對象和指針圖
在 Java 和 .NET 管理代碼中,不可能產生諸如讀寫邊界溢出和讀寫釋放內存的運行時內存錯誤,因為運行時子系統的自動內存管理機制禁止開發人員直接訪問所分配的內存。但是,這種自動化的內存管理並不能阻止程序員忘記對象指針分配內存。只要代碼中存在這種動態分配對象的指針,他們將存在於內存中並不會被自動化的內存管理(垃圾回收技術)所清除。這種錯誤的影響與 C/C++ 中的泄露是一樣的:內存對於其他運行於主機操作系統中的進程變得不可訪問。但是通過使用 Rational Purify 的運行時分析,您能夠指出發生問題的對象指針的準確代碼行(圖 10)。
Rational Purify Object and Reference Graph for a Java Application
圖 10:針對 Java 應用的 Rational Purify 對象和指針圖
點擊放大
運行時行為的文檔
另一種平衡運行時分析的方式是對未來的應用進行運行時行為的文檔化操作。這樣可以幫助您評估工程的全部質量,並測量新引入特徵、應用性能、可靠性、完整性所帶來的影響。 這種實際運行時分析的方式包含了開發和分析數據下的對每次組件或應用疊代的收集運行時數據。這些信息有助於確定工程質量,附加新特徵與錯誤定位的效果。
當您使用了運行時分析工具和源控制工具(如 IBM Rational® ClearCase®),您可以很容易的檢測到哪些源代碼數據庫的改變對於錯誤的構造和/或自動化測試的失敗有關;您能夠發現在成功測試與失敗測試間的源代碼庫的改變。不僅僅是:能夠識別那些改變代碼的歸屬者和引入的準確時間和日期。
高級的運行時分析工具(如 Rational PurifyPlus )提供了分析多重測試運行的特徵,例如,允許用户混合各種不同測試的代碼覆蓋數據,或為連續測試疊代創建單獨的數據集合,如圖 11所示。
Rational Quantify Compare Runs Report
圖 11: Rational Quantify 比對運行報告
點擊放大
圖 11中, Rational Quantify 比對了兩類數據集,並強調了性能改進的調用鏈(綠線)和性能下降的調用鏈(紅線)。最後的數據可以從 Call Graph 視圖和更詳細的 Function List 視圖中獲得。
即使您沒有創建自動化的測試環境,您仍然可以通過利用存儲為 ASCII 文件的運行時分析數據創建自動化的數據分析。圖 12 顯示了一個導入到 Microsoft Excel 中的性能概況的例子。
Rational Quantify Performance Report Imported into Excel
圖 12:Rational Quantify 性能報告被導入到 Excel 文件中
點擊放大
您可以在 Excel 中通過創建簡單的 Visual Basic 程序很容易的實現自動化的數據分析,或以任何流行的腳本語言:Perl, WSH, JavaScript,等等。PurifyPlus for UNIX 包含了腳本集,能夠幫助您管理和分析來自各種測試的數據。
運行時分析:重點是質量
運行時分析擴展了一維標準軟件開發行為:質量關注。它通過更好的理解應用的內部工作過程實現了更高的軟件質量。記住:編譯的源代碼不能證明質量;細節的、可靠的、準確地運行時性能、內存使用和線程與代碼覆蓋分析數據是唯一的決定應用程序不含嚴重錯誤並且高效執行的標準。
參考資料
您可以參閲本文在 developerWorks 全球網站上的 英文原文。
您可以參閲 Rational Edge 電子月刊中文版 的其他文章。
作者簡介
Goran Begic 於1999年加入荷蘭的 Rational 軟件。從那時起,他一直從事於技術支持、區域授權,產品管理和 IBM Rational PurifyPlus 系列開發測試工具的銷售。他還具有實現敏捷開發實踐的經驗。1996年,他獲得了 Zagreb 大學電子工程學士學位。
author photo
Allan Pratt 是 IBM Rational 軟件部門 PurifyPlus 產品團隊的一名首席工程師。他具有二十多年的專業開發經驗。在 1996 年加入 Pure Software 前,他工作於 Atari 的 520ST 時期,之後加入了舊的 Taligent 的工具組。 他總是與系統底層離得比較近:他所參與的項目包括了 68000 彙編代碼的 BIOS 編程,多平台上的鏈接和調試,Unix 腳本與工具,RISC 和 EPIC 處理器的對象代碼指令,及 Java 和 Microsoft .Net 的字節碼指令。