相對于靜態(tài)代碼分析,Profiling是通過收集程序運(yùn)行時的信息來研究程序行為的動態(tài)分析方法。其目的在于定位程序需要被優(yōu)化的部分,從而提高程序的運(yùn)行速度或是內(nèi)存使用效率。收集程序運(yùn)行時信息的方法主要有以下三種:
- 事件方法:對于 Java,可以采用 JVMTI(JVM Tools Interface)API 來捕捉諸如方法調(diào)用、類載入、類卸載、進(jìn)入 / 離開線程等事件,然后基于這些事件進(jìn)行程序行為的分析。
- 統(tǒng)計抽樣方法(sampling): 該方法每隔一段時間調(diào)用系統(tǒng)中斷,然后收集當(dāng)前的調(diào)用棧(call stack)信息,記錄調(diào)用棧中出現(xiàn)的函數(shù)及這些函數(shù)的調(diào)用結(jié)構(gòu),基于這些信息得到函數(shù)的調(diào)用關(guān)系圖及每個函數(shù)的 CPU 使用信息。由于調(diào)用棧的信息是每隔一段時間來獲取的,因此不是非常精確的,但由于該方法對目標(biāo)程序的干涉比較少,目標(biāo)程序的運(yùn)行速度幾乎不受影響。
- 植入附加指令方法(BCI): 該方法在目標(biāo)程序中插入指令代碼,這些指令代碼將記錄 profiling 所需的信息,包括運(yùn)行時間、計數(shù)器的值等,從而給出一個較為精確的內(nèi)存使用情況、函數(shù)調(diào)用關(guān)系及函數(shù)的 CPU 使用信息。該方法對程序執(zhí)行速度會有一定的影響,因此給出的程序執(zhí)行時間有可能不準(zhǔn)確。但是該方法在統(tǒng)計程序的運(yùn)行軌跡方面有一定的優(yōu)勢。
目前市面上的 Java Profiler 工具采用的信息收集方法通常是以上三種方法的任意組合。
Profiler 工具功能簡介
雖然市場上的 Java Profiler 工具有不少,但是基本功能大多相似,本節(jié)首先對這些基本功能進(jìn)行介紹。
- 遙測(Telemetry):遙測是一種用來查看應(yīng)用程序運(yùn)行行為的最簡單的方法。通常會有多個視圖(View)分別實時地顯示 CPU 使用情況、內(nèi)存使用情況、線程狀態(tài)以及其他一些有用的信息,以便用戶能很快地發(fā)現(xiàn)問題的關(guān)鍵所在。
- CPU Telemetry 視圖一般用于顯示整個應(yīng)用程序的 CPU 使用情況,有些工具還能顯示應(yīng)用程序中每個線程的 CPU 使用情況。
- Memory Telemetry 視圖一般用于顯示堆內(nèi)存和非堆內(nèi)存的分配和使用情況。
- Garbage Collection Telemetry 視圖顯示了 JVM 中垃圾收集器的詳細(xì)信息。
- Threads Telemetry 視圖一般用于顯示當(dāng)前運(yùn)行線程的個數(shù)、守護(hù)進(jìn)程的個數(shù)等信息。
- Classes Telemetry 視圖一般用于顯示已經(jīng)載入和還沒有載入的類的數(shù)量。
- 快照(snapshot):應(yīng)用程序啟動后,profiler 工具開始收集各種執(zhí)行數(shù)據(jù),其中一些數(shù)據(jù)直接顯示在遙測視圖中,而另外大部分?jǐn)?shù)據(jù)被保存在內(nèi)部,直到用戶要求獲取快照,基于這些保存的數(shù)據(jù)的統(tǒng)計信息才被 顯示出來??煺瞻藨?yīng)用程序在一段時間內(nèi)的執(zhí)行信息,通常有兩種類型的快照:CPU 快照和內(nèi)存快照。
- CPU 快照主要包含了應(yīng)用程序中函數(shù)的調(diào)用關(guān)系及運(yùn)行時間,這些信息通??梢栽?CPU 快照視圖中進(jìn)行查看。
- 內(nèi)存快照則主要包含了內(nèi)存的分配和使用情況、載入的所有類、存在的對象信息及對象間的引用關(guān)系。這些信息通??梢栽趦?nèi)存快照視圖中進(jìn) 行查看。
- CPU Profiling:CPU Profiling 的主要目的是統(tǒng)計函數(shù)的調(diào)用情況及執(zhí)行時間,或者更簡單的情況就是統(tǒng)計應(yīng)用程序的 CPU 使用情況。通常有兩種方式來顯示 CPU Profiling 結(jié)果:CPU 遙測和 CPU 快照。
- 內(nèi)存 Profiling:內(nèi)存 Profiling 的主要目的是通過統(tǒng)計內(nèi)存使用情況檢測可能存在的內(nèi)存泄露問題及確定優(yōu)化內(nèi)存使用的方向。通常有兩種方式來顯示內(nèi)存 Profiling 結(jié)果:內(nèi)存遙測和內(nèi)存快照
- 線程 Profiling:線程 Profiling 主要用于在多線程應(yīng)用程序中確定內(nèi)存的問題所在。 一般包括三個方面的信息:
- 某個線程的狀態(tài)變化情況
- 死鎖情況
- 某個線程在線程生命期內(nèi)狀態(tài)的分布情況
- Profiling 的啟動設(shè)置:類似于 eclipse 中 Run 和 Debug 的啟動設(shè)置,進(jìn)行 Profiling 之前也需要進(jìn)行啟動設(shè)置,包括:profiling 的模式 (CPU profiling 或內(nèi)存 profiling),信息獲取類型(遙測 , 抽樣統(tǒng)計或者 BCI ) 等等。
- Profiler Preference 設(shè)置:主要用于 Profiler 過濾器(選擇需要關(guān)注的包、類)、取樣間隔時間的設(shè)置等。
Java Profiler 工具介紹
本文接下來將對目前市場上常見的幾種 Java Profiler 工具進(jìn)行介紹。
TPTP
TPTP(Test and Performance Tools Platform)是 eclipse 官方的 Profiling工具插件。TPTP 提供了諸如測試,追蹤(trace),性能測試,圖形界面性能分析等功能。同時 TPTP還是一個可擴(kuò)展的開發(fā)平臺框架,你可以對它加以擴(kuò)展集成到你自己的產(chǎn)品中。TPTP 可以通過 Eclipse update Manager或者是安裝包進(jìn)行安裝,安裝成功后會在 eclipse 中增加如下所示的按鈕,另外一個專門的用于檢查 TPTP profiling 結(jié)果的perspective 也會添加進(jìn) eclipse 中,如下圖所示:
圖 1. TPTPCodePro Profiler
CodePro Profiler 是由 instantiations 公司推出的一款商用 eclipse 插件,它可以通過Eclipse update Manager 進(jìn)行安裝或者是將安裝包直接解壓縮后保存在 eclipse 的指定目錄下。與 TPTP類似,安裝成功后,有一個專門的用于查看 CodePro profiling 結(jié)果的 perspective 會添加進(jìn) eclipse中,如下圖所示:
圖 2. CodeProYourKit Profiler
YourKit Java Profiler 也是一款商用軟件,支持的操作系統(tǒng)包括:Windows, Linux, FreeBSD,Mac OS X, Solaris 以及 HP-UX;支持的 IDE 包括:Eclipse, JBuilder, JDeveloper,NetBeans 以及 Intellij IDEA。安裝成功且首次啟動 YourKit Java Profiler后,會彈出一個對話框,讓用戶選擇 YourKit Java Profiler 要集成進(jìn)的 IDE,并指定該 IDE的安裝路徑,點擊”Install Plugin”按鈕并集成成功之后,Eclipse 中會出現(xiàn)如下圖標(biāo),用戶就可以從 Eclipse 中啟動Profiling,但是 profiling 的結(jié)果需要在 YourKit Java Profiler 中進(jìn)行查詢,如下圖所示:
圖 3. YourKitJProfiler
JProfiler 是由 ej-technologies 推出的一款商用軟件,支持的操作系統(tǒng)有:Windows, Linux,Mac OS X, FreeBSD, Solaris, AIX 以及 HP-UX;支持的 IDE 包括:Eclipse, NetBeans,Intellij IDEA, JBuiler 以及 JDeveloper。安裝成功并首次啟動 JProfiler后,會彈出一個設(shè)置界面,當(dāng)完成左欄所示的那些步驟后,Eclipse 中就會出現(xiàn)如下圖標(biāo),用戶就可以從 Eclipse 中啟動Profiling。與 YourKit Java Profiler 類似,profiling 的結(jié)果需要在 JProfiler中進(jìn)行查詢,如下圖所示:
圖 4. JProfiler
回頁首
Java Profiler 工具比較
本章節(jié)將從如下幾個方面對上述工具進(jìn)行比較:
- 與 Eclipse 的集成性
- TPTP:是一款基于 Eclipse 開發(fā)的插件,因此與 eclipse 的集成性很好。安裝成功后,對 TPTP 的一切設(shè)置與操控都可以在 eclipse 中完成;另外,profiling 的結(jié)果也可以在 eclipse 中進(jìn)行查詢。
- CodePro Profiler: 與 TPTP 類似,CodePro Profiler 也是一款基于 eclipse 開發(fā)的插件,因此與 eclipse 的集成性很好好。用戶在 eclipse 中就可以完成對 profiling 的所有操作。
- YourKit Java Profiler: YourKit Java Profiler 可以說是一個比較獨立的工具,安裝成功后,用戶可以直接在 eclipse 中啟動 YourKit Java Profiler 并對 profiling 選項進(jìn)行配置,但是用戶必須在 YourKit Java Profiler 工具中對 Profiling preferrence 進(jìn)行配置,而且 profiling 信息必須在 YourKit Java Profiler 中進(jìn)行查看。因此和 Eclipse 的集成度一般。
- JProfiler: JProfiler 也是一款比較獨立的工具,安裝成功后,用戶可以直接在 eclipse 中啟動 JProfiler,其他所有操作必須回到 JProfiler 工具中進(jìn)行。因此和 Eclipse 的集成性不好。
- 遙測種類
- TPTP:目前使用的 4.6.2 的版本只提供了線程 Telemetry。
- CodePro Profiler: 總共有五個類型:CPU, 內(nèi)存 , 線程 , 載入的類以及垃圾收集。
- YourKit Java Profiler: 與 CodePro Profiler 相比,缺少載入類的監(jiān)測。
- JProfiler: 與 CodePro Profiler 一樣,總共有五個類型的監(jiān)測方法。
- CPU 快照包含的統(tǒng)計數(shù)據(jù)類型
- TPTP: CPU 快照包含的統(tǒng)計數(shù)據(jù)有:
- 包的組成關(guān)系,細(xì)化到包含的類及類中的方法。
- 方法的調(diào)用關(guān)系:以每個線程為根節(jié)點的方法調(diào)用信息,對于樹中出現(xiàn)的代表方法的每個節(jié)點,列出了該方法的運(yùn)行時間或運(yùn)行時間百分 比,以及該方法被調(diào)用的次數(shù)。
- 方法被調(diào)用情況:列出了直接調(diào)用某方法的其他方法,以及這些方法調(diào)用該方法的次數(shù)及相關(guān)運(yùn)行時間。
- 熱點列表:包含了 CPU 占用時間排列前十的方法、類或包。
- CodePro Profiler: CPU 快照包含的統(tǒng)計數(shù)據(jù)類型有:
- 包的組成關(guān)系,細(xì)化到包含的類及類中的方法。
- 方法的調(diào)用關(guān)系。以樹結(jié)構(gòu)表示,根據(jù)根節(jié)點表示的對象的不同,分為三種類型:以每個線程為根節(jié)點的方法調(diào)用關(guān)系,以整個線程為根 節(jié)點的方法調(diào)用關(guān)系,以及以每個方法為根節(jié)點的方法調(diào)用關(guān)系。對于樹中出現(xiàn)的代表方法的每個節(jié)點,列出了該方法的運(yùn)行時間或運(yùn)行時間百分比,以及由該方法 生成的對象個數(shù)和為這些對象分配的內(nèi)存大小。
- 方法的被調(diào)用關(guān)系。該關(guān)系以樹結(jié)構(gòu)表示,其中根節(jié)點為某個指定的方法,每個節(jié)點的子節(jié)點為父節(jié)點的調(diào)用者。
- 熱點列表:包含了 CPU 占用時間排前的一些方法。
- YourKit Java Profiler:CPU 快照包含的統(tǒng)計數(shù)據(jù)類型與 CodePro Profiler 類似;
- JProfiler:與 CodePro Profiler 相比,缺少以每個方法為根節(jié)點的方法調(diào)用關(guān)系。因此當(dāng)要查看以某個方法為調(diào)用起點的調(diào)用關(guān)系時,需要到以線程為根的樹結(jié)構(gòu)當(dāng)中去查找。另外,方法的被調(diào)用 關(guān)系不是以樹結(jié)構(gòu)來表示的,而是以圖的方式來顯示的,當(dāng)調(diào)用關(guān)系比較復(fù)雜的時候,很難在一個屏幕中看到一個全局關(guān)系圖。
- 內(nèi)存快照包含的統(tǒng)計數(shù)據(jù)類型
- TPTP:包含了類實例的內(nèi)存分配情況,包括實例化的對象個數(shù),以及這些對象的本身占用內(nèi)存的大小。相對于其它 Java Profiler 工具,TPTP 的內(nèi)存快照包含的統(tǒng)計數(shù)據(jù)類型比較少。
- CodePro Profiler: 包含的統(tǒng)計數(shù)據(jù)有
- 類實例的內(nèi)存分配情況,包括實例化的對象個數(shù),以及這些對象的 shallow 和 retained 大小。(Shallow size 就是對象本身占用內(nèi)存的大小,不包含對其他對象的引用;Retained size 是該對象自己的 shallow size,加上從該對象能直接或間接訪問到的 shallow size 之和,即該對象被 GC 之后所能回收到內(nèi)存的總和)。
- 最大對象列表:包含了 retained 大小排前的一些對象。
- 有可能存在內(nèi)存泄漏的對象列表:包含了有可能存在內(nèi)存泄漏的對象以及可能性大小。
- YourKit Java Profiler:與 CodePro Profiler 相比,缺少內(nèi)存泄露對象列表這一項。
- JProfiler:與 CodePro Profiler 相比,缺少 retained size 統(tǒng)計數(shù)據(jù)及內(nèi)存泄露對象列表。
- 源代碼定位功能,即在快照中選中某個類、成員變量或者方法時,可以在源代碼中定位到對應(yīng)的定義。
- TPTP:只能定位到某個類,無法定位到方法或其中的成員變量。
- CodePro Profiler: 擁有該功能,但是只能定位到類及成員變量,無法定位到方法。
- YourKit Java Profiler:可以定位到類、成員變量及方法。
- JProfiler:與 CodePro Profiler 類似。
- 快照操作,主要從快照的獲取、快照的保存及快照的比較這三方面進(jìn)行比較。
- TPTP:當(dāng)應(yīng)用程序啟動后,用戶可以選擇在適當(dāng)?shù)臅r候進(jìn)行快照獲??;這些快照不會自動保存,因此當(dāng) eclipse 關(guān)閉后,這些快照數(shù)據(jù)將會消失,但是用戶可以通過 export 的方式將需要的快照保存下來。
- CodePro Profiler: 當(dāng)應(yīng)用程序啟動后,用戶可以選擇在適當(dāng)?shù)臅r候進(jìn)行快照獲?。贿@些快照會被自動保存在 Eclipse Workspace 之外的一個臨時的空間,當(dāng) eclipse 關(guān)閉后,這些快照將會消失,用戶可以通過 export 的方式將需要的快照保存下來;CodePro Profiler 還提供了快照的比較功能,不過前提是這兩個快照的類型必須相同(例如:都是以 sampling 模式或 BCI 模式運(yùn)行的)。
- YourKit Java Profiler:當(dāng)應(yīng)用程序啟動后,用戶可以選擇在適當(dāng)?shù)臅r候進(jìn)行快照獲取,針對內(nèi)存快照,YourKit Java Profiler 還提供了自動獲取快照的功能;這些快照會被自動保存到一個臨時的文件夾中,eclipse 關(guān)閉后,這些文件不會消失;另外,YourKit Java Profiler 也提供了快照比較功能。
- JProfiler:工具會要求你指定一個目錄來保存該 snapshot。
- 性能,在 sampling 模式下,這些工具的性能相差不大,這里主要比較在 BCI 模式下的性能。
- TPTP:目前使用的 4.6.2 的版本沒有 BCI 模式。
- CodePro Profiler:當(dāng)程序比較大的情況下,采用 BCI 模式進(jìn)行 profiling 的速度比較慢;另外,在獲取內(nèi)存泄露候選者的時候,速度也是相當(dāng)慢。(當(dāng)程序代碼量 5 萬行時,用 CodePro Profiler 進(jìn)行 Profiling 需要 5 分鐘,在獲取內(nèi)存泄露候選者時,需要花費 20 分鐘)
- YourKit Java Profiler:BCI 模式下的運(yùn)行速度還可以。(當(dāng)程序代碼量為 5 萬行時,需要 1 分鐘)
- JProfiler:感覺不出程序運(yùn)行速度受影響。(當(dāng)程序代碼量為 5 萬行時,需要半分鐘)
- 健壯性,采用 CodePro Profiler 對比較大的應(yīng)用程序進(jìn)行 profiling 時,很容易出現(xiàn)棧溢出的錯誤。
結(jié)論
TPTP 是一款基于 eclipse 的開源軟件,且提供的功能比較簡單,因此適用于基于 eclipse開發(fā)的應(yīng)用程序,且該應(yīng)用程序比較簡單的情況;Codepro Profiler 提供的功能相對來說比較豐富,且與 eclipse的集成性很好,但是在性能方面有待改善,因此適用于基于 eclipse 開發(fā)的應(yīng)用程序,且對性能要求不高的情況;YourKit JavaProfiler,JProfiler 與 Eclipse 的集成性都屬于一般,提供的功能也比較豐富,且性能不錯,因此適用于對 eclipse集成度要求不高,且對性能要求較高的情況。
參考資料
學(xué)習(xí)
作者簡介
周鵬,CSTL 軟件工程師,從事過三年Mainframe 上系統(tǒng)軟件的開發(fā),一年 Director6.1 在 IBM pSeries 的測試工作以及測試環(huán)境的維護(hù)工作。目前負(fù)責(zé)Director6.1 與其他產(chǎn)品,如 IBM Tivoli, HP OVO, CA NSM 等的集成開發(fā)工作。
徐曉琴,Verigy 軟件工程師,有多年Java, C++ 的開發(fā)經(jīng)驗。