了解關(guān)于 OProfile 的知識(shí),學(xué)習(xí)如何在基于 IBM® POWER™ 處理器、運(yùn)行 Linux™ 的服務(wù)器上使用它。首先,閱讀關(guān)于 OProfile 的概述,并了解它在 Linux on POWER 上的實(shí)現(xiàn),然后跟隨作者給出的兩個(gè)例子,學(xué)習(xí)如何在 Linux on POWER 平臺(tái)上使用 OProfile 分析代碼和結(jié)果。
簡(jiǎn)介
作為一名開(kāi)發(fā)人員,在試圖提高代碼效率時(shí),您可能發(fā)現(xiàn)性能瓶頸是您要面對(duì)的最困難的任務(wù)之一。代碼分析(code profiling)是一種可以使這項(xiàng)任務(wù)變得更容易的方法。代碼分析包括對(duì)那些表示運(yùn)行系統(tǒng)上的某些處理器活動(dòng)的數(shù)據(jù)樣本進(jìn)行分析。OProfile 為 POWER 上的 Linux 提供了這種解決方案。OProfile 被包含在最新的 IBM® 支持的 Linux for POWER 發(fā)行版本中:Red Hat Enterprise Linux 4 (RHEL4) 和 SUSE LINUX Enterprise Server 9 (SLES9)。本文將介紹 OProfile for Linux on POWER,并提供兩個(gè)例子,演示如何使用它來(lái)發(fā)現(xiàn)性能瓶頸。
代碼分析概述
OProfile for Linux on POWER 使用了一個(gè)內(nèi)核模塊和一個(gè)用戶空間守護(hù)進(jìn)程,前者可以訪問(wèn)性能計(jì)數(shù)寄存器,后者在后臺(tái)運(yùn)行,負(fù)責(zé)從這些寄存器中收集數(shù)據(jù)。在啟動(dòng)守護(hù)進(jìn)程之前, OProfile 將配置事件類型以及每種事件的樣本計(jì)數(shù)(sample count)。如果沒(méi)有配置任何事件,那么 OProfile 將使用 Linux on POWER 上的默認(rèn)事件,即 CYCLES,該事件將對(duì)處理器循環(huán)進(jìn)行計(jì)數(shù)。事件的樣本計(jì)數(shù)將決定事件每發(fā)生多少次計(jì)數(shù)器才增加一次。OProfile 被設(shè)計(jì)成可以在低開(kāi)銷下運(yùn)行,從而使后臺(tái)運(yùn)行的守護(hù)進(jìn)程不會(huì)擾亂系統(tǒng)性能。
OProfile 具有對(duì) POWER4™、POWER5™ 和 PowerPC® 970 處理器的內(nèi)核支持。PowerPC 970 和 POWER4 處理器有 8 個(gè)計(jì)數(shù)寄存器,而 POWER5 處理器有 6 個(gè)計(jì)數(shù)寄存器。在不具備 OProfile 內(nèi)核支持的架構(gòu)上使用的則是計(jì)時(shí)器(timer)模式。在這種模式下,OProfile 使用了一個(gè)計(jì)數(shù)器中斷,對(duì)于禁用中斷的代碼,OProfile 不能對(duì)其進(jìn)行分析。
OProfile 工具
與 OProfile 內(nèi)核支持一起提供的還有一些與內(nèi)核交互的用戶空間工具,以及分析收集到的數(shù)據(jù)的工具。如前所述,OProfile 守護(hù)進(jìn)程收集樣本數(shù)據(jù)。控制該守護(hù)進(jìn)程的工具稱作 opcontrol。表 1 列出了用于 opcontrol 的一些常見(jiàn)的命令行選項(xiàng)。本文的后面還將描述 opreport 和 opannotate 這兩個(gè)工具,它們都是用于分析收集到的數(shù)據(jù)的工具。在 OProfile 手冊(cè)的第 2.2 節(jié)中,可以找到對(duì)所有 OProfile 工具的概述。(請(qǐng)參閱參考資料。)
RHEL4 和 SLES9 上支持的處理器事件類型是不同的,正如不同 POWER 處理器上支持的事件類型也會(huì)有所變化一樣。您可以使用 opcontrol 工具和 --list-events 選項(xiàng)獲得自己平臺(tái)所支持的那些事件的列表。
表 1. opcontrol 命令行選項(xiàng)
| opcontrol 選項(xiàng) | 描述 |
| --list-events | 列出處理器事件和單元屏蔽(unit mask) |
| --vmlinux=<kernel image> | 將要分析的內(nèi)核鏡像文件 |
| --no-vmlinux | 不分析內(nèi)核 |
| --reset | 清除當(dāng)前會(huì)話中的數(shù)據(jù) |
| --setup | 在運(yùn)行守護(hù)進(jìn)程之前對(duì)其進(jìn)行設(shè)置 |
| --event=<processor event> | 監(jiān)視給定的處理器事件 |
| --start | 開(kāi)始取樣 |
| --dump | 使數(shù)據(jù)流到守護(hù)進(jìn)程中 |
| --stop | 停止數(shù)據(jù)取樣 |
| -h | 關(guān)閉守護(hù)進(jìn)程 |
OProfile 例子
您可以使用 OProfile 來(lái)分析處理器周期、TLB 失誤、內(nèi)存引用、分支預(yù)測(cè)失誤、緩存失誤、中斷處理程序,等等。同樣,您可以使用 opcontrol 的 --list-events 選項(xiàng)來(lái)提供完整的特定處理器上可監(jiān)視事件列表。
下面的例子演示了如何使用 OProfile for Linux on POWER。第一個(gè)例子監(jiān)視處理器周期,以發(fā)現(xiàn)編寫(xiě)不當(dāng)、會(huì)導(dǎo)致潛在性能瓶頸的算法。雖然這是一個(gè)很小的例子,但是當(dāng)您分析一個(gè)應(yīng)用程序,期望發(fā)現(xiàn)大部分處理器周期究竟用在什么地方時(shí),仍可以借鑒這里的方法。然后您可以進(jìn)一步分析這部分代碼,看是否可以對(duì)其進(jìn)行優(yōu)化。
第二個(gè)例子要更為復(fù)雜一些 —— 它演示了如何發(fā)現(xiàn)二級(jí)(level 2,L2)數(shù)據(jù)緩存失誤,并為減少數(shù)據(jù)緩存失誤的次數(shù)提供了兩套解決方案。
例 1: 分析編寫(xiě)不當(dāng)?shù)拇a
這個(gè)例子的目的是展示如何編譯和分析一個(gè)編寫(xiě)不當(dāng)?shù)拇a示例,以分析哪個(gè)函數(shù)性能不佳。這是一個(gè)很小的例子,只包含兩個(gè)函數(shù) —— slow_multiply() 和 fast_multiply() —— 這兩個(gè)函數(shù)都是用于求兩個(gè)數(shù)的乘積,如下面的清單 1 所示。
清單 1. 兩個(gè)執(zhí)行乘法的函數(shù)
int fast_multiply(x, y) { return x * y;}int slow_multiply(x, y) { int i, j, z; for (i = 0, z = 0; i < x; i++) z = z + y; return z;}int main(){ int i,j; int x,y; for (i = 0; i < 200; i ++) { for (j = 0; j " 30 ; j++) { x = fast_multiply(i, j); y = slow_multiply(i, j); } } return 0;}
|
分析這個(gè)代碼,并使用 opannotate 對(duì)其進(jìn)行分析,該工具使您可以用 OProfile 注釋查看源代碼。首先必須利用調(diào)試信息來(lái)編譯源代碼,opannotate 要用它來(lái)添加注釋。使用 Gnu Compiler Collections C 編譯器,即 gcc,通過(guò)運(yùn)行以下命令來(lái)編譯清單 1 中的例子。注意,-g 標(biāo)志意味著要添加調(diào)試信息。
gcc -g multiply.c -o multiply
|
接下來(lái),使用 清單 2 中的命令分析該代碼,然后使用 CYCLES 事件計(jì)算處理器周期,以分析結(jié)果。
清單 2. 用來(lái)分析乘法例子的命令
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup --event=CYCLES:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./multiply# opcontrol --dump# opcontrol --stopStopping profiling.# opcontrol -hStopping profiling.Killing daemon.
|
最后,使用 opannotate 工具和 --source 選項(xiàng)生成源代碼,或者和 --assembly 選項(xiàng)一起生成匯編代碼。具體使用這兩個(gè)選項(xiàng)中的哪一個(gè)選項(xiàng),或者是否同時(shí)使用這兩個(gè)選項(xiàng),則取決于您想要分析的詳細(xì)程度。對(duì)于這個(gè)例子,只需使用 --source 選項(xiàng)來(lái)確定大部分處理器周期發(fā)生在什么地方即可。
清單 3. 對(duì)乘法例子的 opannotate 結(jié)果的分析
# opannotate --source ./multiply/* * Command line: opannotate --source ./multiply * * Interpretation of command line: * Output annotated source file with samples * Output all files * * CPU: ppc64 POWER5, speed 1656.38 MHz (estimated) * Counted CYCLES events (Processor cycles) with a unit mask of0x00 (No unit mask) count 1000 *//* * Total samples for file : "/usr/local/src/badcode/multiply.c" * * 6244 100.000 */ :int fast_multiply(x, y) 36 0.5766 :{ /* fast_multiply total: 79 1.2652 */ 26 0.4164 : return x * y; 17 0.2723 :} : :int slow_multiply(x, y) 50 0.8008 :{ /* slow_multiply total: 6065 97.1332 */ : int i, j, z; 2305 36.9154 : for (i = 0, z = 0; i " x; i++) 3684 59.0006 : z = z + y; 11 0.1762 : return z; 15 0.2402 :} : :int main() :{ /* main total: 100 1.6015 */ : int i,j; : int x,y; : 1 0.0160 : for (i = 0; i " 200; i ++) { 6 0.0961 : for (j = 0; j " 30 ; j++) { 75 1.2012 : x = fast_multiply(i, j); 18 0.2883 : y = slow_multiply(i, j); : } : } : return 0; :}
|
清單 3 中下面的幾行將顯示兩個(gè)乘法函數(shù)中所使用的 CYCLES 數(shù):
36 0.5766 :{ /* fast_multiply total: 79 1.2652 */
|
50 0.8008 :{ /* slow_multiply total: 6065 97.1332 */
|
您可以看到,fast_mulitply() 只使用了 79 個(gè)樣本,而 slow_multiply() 使用了 6065 個(gè)樣本。雖然這是一個(gè)很小的例子,在現(xiàn)實(shí)中不大可能出現(xiàn),但它仍然足以演示如何剖析代碼,并為發(fā)現(xiàn)性能瓶頸而對(duì)其進(jìn)行分析。
例 2:發(fā)現(xiàn)二級(jí)數(shù)據(jù)緩存失誤
這個(gè)例子比第一個(gè)例子要復(fù)雜一些,它需要發(fā)現(xiàn)二級(jí)(L2)數(shù)據(jù)緩存失誤。POWER 處理器包含芯片二級(jí)緩存(on-chip L2 cache),這是鄰近處理器的一種高速存儲(chǔ)器。處理器從 L2 緩存中訪問(wèn)經(jīng)常修改的數(shù)據(jù)。當(dāng)兩個(gè)處理器共享一個(gè)數(shù)據(jù)結(jié)構(gòu),并同時(shí)修改那個(gè)數(shù)據(jù)結(jié)構(gòu)時(shí),就有可能引發(fā)問(wèn)題。CPU1 在它的 L2 緩存中包含數(shù)據(jù)的一個(gè)副本,而 CPU2 修改了這個(gè)共享的數(shù)據(jù)結(jié)構(gòu)。CPU1 L2 緩存中的副本現(xiàn)在是無(wú)效的,必須進(jìn)行更新。CPU1 必須花費(fèi)大量步驟從主存中檢索數(shù)據(jù),這需要占用額外的處理器周期。圖 1 展示了兩個(gè)處理器,它們?cè)诟髯缘?L2 緩存中包含一個(gè)共享數(shù)據(jù)結(jié)構(gòu)的一個(gè)副本。
圖 1. 共享一個(gè)數(shù)據(jù)結(jié)構(gòu)的兩個(gè)處理器
在這個(gè)例子中,您將查看這個(gè)數(shù)據(jù)結(jié)構(gòu)(如清單 4 所示),并分析兩個(gè)處理器同時(shí)修改這個(gè)數(shù)據(jù)結(jié)構(gòu)時(shí)出現(xiàn)的情景)。然后觀察數(shù)據(jù)緩存失誤,并考察用來(lái)修正這個(gè)問(wèn)題的兩種解決方案。
清單 4. 共享的數(shù)據(jù)結(jié)構(gòu)
struct shared_data_struct { unsigned int data1; unsigned int data1;}
|
清單 5 中的程序使用 clone() 系統(tǒng)調(diào)用和 VM_CLONE 標(biāo)志生成一個(gè)子進(jìn)程。VM_CLONE 標(biāo)志會(huì)導(dǎo)致子進(jìn)程和父進(jìn)程在同一個(gè)存儲(chǔ)空間中運(yùn)行。父線程修改該數(shù)據(jù)結(jié)構(gòu)的第一個(gè)元素,而子線程則修改第二個(gè)元素。
清單 5. 演示 L2 數(shù)據(jù)緩存失誤的代碼示例
#include <stdlib.h>#include <sched.h>struct shared_data_struct { unsigned int data1; unsigned int data2;};struct shared_data_struct shared_data;static int inc_second(struct shared_data_struct *);int main(){ int i, j, pid; void *child_stack; /* allocate memory for other process to execute in */ if((child_stack = (void *) malloc(4096)) == NULL) { perror("Cannot allocate stack for child"); exit(1); } /* clone process and run in the same memory space */ if ((pid = clone((void *)&inc_second, child_stack, CLONE_VM, &shared_data)) < 0) { perror("clone called failed."); exit(1); } /* increment first member of shared struct */ for (j = 0; j < 2000; j++) { for (i = 0; i < 100000; i++) { shared_data.data1++; } } return 0;}int inc_second(struct shared_data_struct *sd){ int i,j; /* increment second member of shared struct */ for (j = 1; j < 2000; j++) { for (i = 1; i < 100000; i++) { sd->data2++; } }}
|
使用 gcc 編譯器,運(yùn)行清單 6 中的命令不帶優(yōu)化地編譯這個(gè)示例程序。
清單 6. 用于編譯清單 5 中例子代碼的命令
gcc -o cache-miss cache-miss.c
|
現(xiàn)在您可以用 OProfile 分析上述程序中出現(xiàn)的 L2 數(shù)據(jù)緩存失誤。
對(duì)于這個(gè)例子,作者在一臺(tái) IBM eServer™ OpenPower™ 710 上執(zhí)行和分析了這個(gè)程序,該機(jī)器有兩個(gè) POWER5 處理器,并運(yùn)行 SLES9 Service Pack 1 (SLES9SP1)。將 --list-events 標(biāo)志傳遞給 opcontrol,以判斷是哪一個(gè)事件負(fù)責(zé)監(jiān)視 L2 數(shù)據(jù)緩存失誤。對(duì)于基于 POWER5 處理器的、運(yùn)行 SLES9SP1 的系統(tǒng),由 PM_LSU_LMQ_LHR_MERGE_GP9 事件監(jiān)視 L2 數(shù)據(jù)緩存失誤。如果您將樣本計(jì)數(shù)設(shè)置為 1000,比如在這個(gè)例子中,那么 OProfile 將從每 1000 個(gè)硬件事件抽取一個(gè)樣本。如果使用不同的平臺(tái),例如基于 POWER4 處理器的服務(wù)器,那么這樣的事件也會(huì)有所不同。
使用 清單 7 中的命令分析這個(gè)例子代碼,如下所示:
清單 7. 用來(lái)分析清單 5 所示例子中的 L2 數(shù)據(jù)緩存失誤的命令
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup –event=PM_LSU_LMQ_LHR_MERGE_GP9:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./cache-miss# opcontrol --dump# opcontrol -hStopping profiling.Killing daemon.# opreport -l ./cache-miss CPU: ppc64 POWER5, speed 1656.38 MHz (estimated)Counted PM_LSU_LMQ_LHR_MERGE_GP9 events (Dcache miss occurred for the same real cache line as earlier req, merged into LMQ) with a unit mask of 0x00 (No unit mask) count 1000samples % symbol name47897 58.7470 main33634 41.2530 inc_second
|
在分析來(lái)自 opreport 的結(jié)果時(shí),您可以看到,在函數(shù) main() 和 inc_second() 中存在很多緩存失誤。opreport 的 -l 選項(xiàng)將輸出符號(hào)信息,而實(shí)質(zhì)上輸出的應(yīng)該只是二進(jìn)制映像名。同樣,緩存失誤的起因也是兩個(gè)處理器修改一個(gè)共享的數(shù)據(jù)結(jié)構(gòu),這個(gè)數(shù)據(jù)結(jié)構(gòu)大小為 8 字節(jié),放在一個(gè) 128 字節(jié)的緩存行中。
消除數(shù)據(jù)緩存失誤的一種方法是填充數(shù)據(jù)結(jié)構(gòu),使得它的每一個(gè)元素都存儲(chǔ)在各自的緩存行中。清單 8 包含一個(gè)修改后的結(jié)構(gòu),其中有 124 字節(jié)的填充物。
清單 8. 帶填充物的數(shù)據(jù)結(jié)構(gòu),每個(gè)元素放進(jìn)不同的緩存行中
struct shared_data_struct { unsigned int data1; char pad[124]; unsigned int data1;
|
圖 2 展示了在填充數(shù)據(jù)結(jié)構(gòu)后,如何使得每個(gè)處理器上的每個(gè)數(shù)據(jù)元素都存儲(chǔ)在各自的緩存行中。
圖 2. 共享填充后的數(shù)據(jù)結(jié)構(gòu)的兩個(gè)處理器
像前面那樣重新編譯該程序,但是這一次使用修改后的數(shù)據(jù)結(jié)構(gòu)。然后使用 清單 9 中的命令再次分析結(jié)果。
清單 9. 填充數(shù)據(jù)結(jié)構(gòu)后用于 profile L2 數(shù)據(jù)緩存失誤的命令
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup –event=PM_LSU_LMQ_LHR_MERGE_GP9:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./cache-miss# opcontrol --dump# opcontrol -hStopping profiling.Killing daemon.# opreport -l ./cache-miss error: no sample files found: profile specification too strict ?
|
Opreport 表明,由于沒(méi)有發(fā)現(xiàn)抽樣數(shù)據(jù),所以可能存在錯(cuò)誤。然而,隨著對(duì)共享數(shù)據(jù)結(jié)構(gòu)的修改,這是可以預(yù)期的,因?yàn)槊總(gè)數(shù)據(jù)元素都在自己的緩存行中,所以不存在 L2 緩存失誤。
現(xiàn)在可以考察 L2 緩存失誤在處理器周期上的代價(jià)。首先,分析使用未填充的原有共享數(shù)據(jù)結(jié)構(gòu)的代碼(清單 4)。您將進(jìn)行抽樣的事件是 CYCLES。使用 清單 10 中的命令針對(duì) CYCLES 事件分析這個(gè)例子。
清單 10. 用于 profile 清單 5 所示例子中處理器周期數(shù)的命令
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup –event=CYCLES:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./cache-miss# opcontrol --dump# opcontrol -hStopping profiling.Killing daemon.# opreport -l ./cache-miss CPU: ppc64 POWER5, speed 1656.38 MHz (estimated)Counted CYCLES events (Processor cycles) with a unit mask of 0x00 (No unit mask) count 1000samples % symbol name121166 53.3853 inc_second105799 46.6147 main
|
現(xiàn)在,使用 清單 11 中的命令分析使用填充后的數(shù)據(jù)結(jié)構(gòu)的例子代碼(清單 8)。
清單 11. 用于分析使用填充后的數(shù)據(jù)結(jié)構(gòu)的例子中處理器周期數(shù)的命令
# opcontrol --vmlinux=/boot/vmlinux-2.6.5-7.139-pseries64# opcontrol --reset# opcontrol --setup –event=CYCLES:1000# opcontrol --startUsing 2.6+ OProfile kernel interface.Reading module info.Using log file /var/lib/oprofile/oprofiled.logDaemon started.Profiler running.# ./cache-miss# opcontrol --dump# opcontrol -hStopping profiling.Killing daemon.# opreport -l ./cache-miss CPU: ppc64 POWER5, speed 1656.38 MHz (estimated)Counted CYCLES events (Processor cycles) with a unit mask of 0x00 (No unit mask) count 1000samples % symbol name104916 58.3872 inc_second74774 41.6128 main
|
不出所料,隨著 L2 緩存失誤數(shù)量的增加,處理器周期數(shù)也有所增加。其主要原因是,與從 L2 緩存取數(shù)據(jù)相比,從主存獲取數(shù)據(jù)代價(jià)昂貴。
避免兩個(gè)處理器之間緩存失誤的另一種方法是在相同處理器上運(yùn)行兩個(gè)線程。通過(guò)使用 Cpu 相似性(affinity),將一個(gè)進(jìn)程綁定到一個(gè)特定的處理器,下面的例子演示了這一點(diǎn)。在 Linux 上,sched_setaffinity() 系統(tǒng)調(diào)用在一個(gè)處理器上運(yùn)行兩個(gè)線程。 清單 12 提供了原來(lái)的示例程序的另一個(gè)變體,其中使用 sched_setaffinity() 調(diào)用來(lái)執(zhí)行這一操作。
清單 12. 利用 cpu 相似性來(lái)避免 L2 緩存失誤的示例代碼
#include <stdlib.h>#include <sched.h>struct shared_data_struct { unsigned int data1; unsigned int data2;};struct shared_data_struct shared_data;static int inc_second(struct shared_data_struct *);int main(){ int i, j, pid; cpu_set_t cmask; unsigned long len = sizeof(cmask); pid_t p = 0; void *child_stack; __CPU_ZERO(&cmask); __CPU_SET(0, &cmask); /* allocate memory for other process to execute in */ if((child_stack = (void *) malloc(4096)) == NULL) { perror("Cannot allocate stack for child"); exit(1); } /* clone process and run in the same memory space */ if ((pid = clone((void *)&inc_second, child_stack, CLONE_VM, &shared_data)) < 0) { perror("clone called failed"); exit(1); } if (!sched_setaffinity(0, len, &cmask)) { printf("Could not set cpu affinity for current process.\n"); exit(1); } if (!sched_setaffinity(pid, len, &cmask)) { printf("Could not set cpu affinity for cloned process.\n"); exit(1); } /* increment first member of shared struct */ for (j = 0; j < 2000; j++) { for (i = 0; i < 100000; i++) { shared_data.data1++; } } return 0;}int inc_second(struct shared_data_struct *sd){ int i,j; /* increment second member of shared struct */ for (j = 1; j < 2000; j++) { for (i = 1; i < 100000; i++) { sd->data2++; } }}
|
這個(gè)例子在同處理器上運(yùn)行兩個(gè)線程,共享數(shù)據(jù)結(jié)構(gòu)存放在一個(gè)處理器上的一個(gè) L2 緩存行中。這樣應(yīng)該可以導(dǎo)致零緩存失誤。使用前面描述的步驟分析緩存失誤,以驗(yàn)證在一個(gè)處理器上運(yùn)行兩個(gè)進(jìn)程時(shí),是否不存在 L2 緩存失誤。對(duì)于數(shù)據(jù)緩存失誤這個(gè)問(wèn)題,第三種解決方法是使用編譯器優(yōu)化,這樣可以減少緩存失誤的數(shù)量。然而,在某些環(huán)境下,這不是一個(gè)合適的選擇,您仍然必須分析代碼,并對(duì)不良性能做出改正。
結(jié)束語(yǔ)
分析是開(kāi)發(fā)過(guò)程中最困難的任務(wù)之一。為了使代碼獲得最佳性能,好的工具是必不可少的。OProfile 就是這樣一種工具,目前它提供了針對(duì) Linux on POWER 的分析功能。對(duì)于其他平臺(tái)上的可以快速移植到 Linux on POWER 的 Linux,還有其他許多性能和調(diào)試工具。除了處理器事件的類型有所差別外,在基于 POWER 處理器的 Linux 平臺(tái)上運(yùn)行 OProfile 與在其他架構(gòu)上運(yùn)行 OProfile 是類似的。所以,如果在其他平臺(tái)上使用過(guò) OProfile,那么您應(yīng)該在很短時(shí)間內(nèi)就可以知道如何在 Linux on POWER 上運(yùn)行 OProfile。
致謝
我要感謝 Linda Kinnunen,是她提供了文檔模板并對(duì)本文進(jìn)行了審校,我還要感謝 Maynard Johnson 對(duì)本文進(jìn)行了技術(shù)上的審校。