OProfile 是一個低管理費用的系統全局的性能監視工具。它使用處理器上的性能監視硬件來檢索關於內核以及系統上的可執行文件的信息,例如內存是何時被引用的;L2 緩存請求數量;收到的硬件中斷數量等。在紅帽企業 Linux 系統上,你必須安裝 oprofile RPM 軟件包才能使用該工具。
許多處理器都包含專用的性能監視硬件。該硬件能夠在某些事件發生時(如所請求的數據不在緩存內)檢測到它們。硬件通常是一個或多個計數器(counters),它們在每次事件發生時都遞增一位。當計數器的值“翻轉還原”,中斷就會生成,從而能夠控制性能監視的詳細程度(以及由此帶來的費用)。
OProfile 使用這個硬件(若沒有性能監視硬件則使用一個基於計時器的代用品)來在每次計數器生成中斷時收集與性能相關的數據樣品(samples)。這些樣品被定期寫入磁盤;稍後,其中的數據就會被用來生成系統級別和應用程序級別的性能報告。
OProfile 是一個很有用的工具,但是請了解使用它的一些局限性:
-
對共享庫的使用 — 除非使用 --separate=library 選項,共享庫中的編碼樣品不會成為某個特定應用程序的屬性。
-
性能監視樣品不精確 — 當性能監視註冊器引發了抽樣行動,中斷處理將不會明確給出例外的類型。由於處理器要無序地執行指令,樣品可能會在附近的指令上被抽取。
-
oprofpp 不能夠正確地歸類內聯函數樣品 — oprofpp 使用一個簡單的地址範圍機制來決定它所在的是哪個函數的地址。內聯函數樣品不從屬於那個內聯函數,而是從屬於那個內聯函數所插入的函數。
-
OProfile 從多次運行中積累數據 — OProfile 是一個系統範圍內的建檔器,它預計進程會被多次啟動和關閉。這樣,樣品就會從多次運行實例中被積累下來。使用 opcontrol --reset 來清除從以前運行實例中抽取的樣品。
-
非 CPU 約束的性能問題 — OProfile 能夠找出受 CPU 約束的進程的問題。OProfile 不會識別正處於睡眠狀態的進程,因為這些進程正在等待鎖或其它事件的發生(如等待 I/O 設備完成操作)。
在Redhat Enterprise Linux 中,只有多處理器(SMP)內核才啟用了 OProfile 支持。要判定運行的是哪個內核,使用以下命令:
uname -r |
如果返回的內核版本以 .entsmp 結束,運行的就是多處理器內核。否則,即使系統不是多處理器系統,也請通過紅帽網絡或發行光盤來安裝它。多處理器內核可以在單處理器內核上運行。
第1節 工具總覽
表1提供了對 oprofile 軟件包中包括的工具的總覽。
命令 | 描述 |
---|---|
opcontrol | 配置要收集的數據。詳情請參閱第2 節。 |
op_help | 顯示系統處理器的可用事件以及每個事件的簡單描述。 |
op_merge | 合並同一可執行文件的多個樣品。詳情請參閱第5.4 節。 |
op_time | 提供對所有建檔的可執行文件的總覽。詳情請參閱第5.1 節。 |
op_to_source | 如果應用程序使用調試符號編譯了,創建帶註解的源碼。詳情請參閱第5.3 節。 |
oprofiled | 作為守護進程來運行,定期把樣品數據寫入磁盤。 |
oprofpp | 檢索檔案數據。詳情請參閱第5.2 節。 |
op_import | 把樣品數據庫文件從異類二進制格式轉換成系統的本地原始格式。只有在分析不同體系的樣品數據庫時才使用該選項。 |
表1. OProfile 命令
第2節 配置 OProfile
在運行 OProfile 之前,它必須被配置。至少需要選擇是否要監視內核。以下各節描述了如何使用opcontrol 工具來配置 OProfile。在 opcontrol 命令被執行時,設置選項就會被保存到/root/.oprofile/daemonrc 文件中。
2.1. 指定內核
首先,配置 OProfile 是否應該監視內核。這是在啟動 OProfile 前唯一所需的配置選項。其它選項都是可選的。
要監視內核,以根用戶身份執行以下命令:
opcontrol --vmlinux=/boot/vmlinux-`uname -r` |
要配置 OProfile 不監視內核,以根用戶身份執行以下命令:
opcontrol --no-vmlinux |
這個命令還會載入 oprofile 內核模塊(如果還沒有被載入),並創建 /dev/oprofile/ 目錄(如果不存在)。關於這個目錄的詳情,請參閱第 43.6 節。
註記 | |
---|---|
即便 OProfile 被配置成不為內核建檔,SMP 內核仍舊必須運行,這樣,oprofile 模塊才會被載入。 |
設置樣品是否應在內核中收集只會改變所收集的數據,而不會改變收集數據的方法或貯存地點。要為內核和應用程序庫生成不同的樣品文件,請參閱第2.3 節。
2.2. 設置要監視的事件
多數處理器包含計數器(counters)。它們被 OProfile 用來監視指定的事件。如表 43-2所示,可用的計數器的數量要根據處理器而定。
處理器 | cpu_type | 計數器數量 |
---|---|---|
Pentium Pro | i386/ppro | 2 |
Pentium II | i386/pii | 2 |
Pentium III | i386/piii | 2 |
Pentium 4 (無超線程) | i386/p4 | 8 |
Pentium 4 (有超線程) | i386/p4-ht | 4 |
Athlon | i386/athlon | 4 |
AMD64 | x86-64/hammer | 4 |
Itanium | ia64/itanium | 4 |
Itanium 2 | ia64/itanium2 | 4 |
TIMER_INT | 計時器(timer) | 1 |
IBM eServer iSeries | 計時器(timer) | 1 |
IBM eServer pSeries | 計時器(timer) | 1 |
IBM eServer S/390 | 計時器(timer) | 1 |
IBM eServer zSeries | 計時器(timer) | 1 |
表2. OProfile 處理器和計數器
使用表2的信息來校驗所檢測到的處理器類型是否正確,並且判定能夠被同時監視的事件數量。如果處理器沒有支持的性能監視硬件,計時器(timer)就會被用作處理器類型。
如果使用了 timer,事件就不能為任何處理器設置,因為硬件不支持硬件性能計數器。相反,計時器中斷會被用來建檔。
如果 timer 沒有被用作處理器類型,監視的事件就可以被改變,處理器的計數器0就會被默認設置為基於時間的事件。如果處理器上有多個計數器,0以外的計數器就不會被默認設置任何事件。被監視的默認事件顯示在表3中。
處理器 | 計數器0的默認事件 | 描述 |
---|---|---|
Pentium Pro, Pentium II, Pentium III, Athlon, AMD64 | CPU_CLK_UNHALTED | 處理器的時鐘沒有停止 |
Pentium 4 (HT 和非 HT) | GLOBAL_POWER_EVENTS | 處理器沒有停止的時間 |
Itanium 2 | CPU_CYCLES | CPU 周期 |
TIMER_INT | (none) | 每個計時器中斷的抽樣 |
表3. 默認事件
可以被同時監視的事件數量是由處理器的計數器數量決定的。不過,這不是一對一的情況;在某些處理器上,某些事件必須被映射到指定的計數器上。要判定可用的計數器數量,執行以下命令:
cat /dev/oprofile/cpu_type |
可用的事件要根據處理器類型而定。要判定可被建檔的事件,以根用戶身份執行以下命令(該列表是針對系統處理器類型特有的):
op_help |
每個計數器的事件都可以通過命令行被配置,也可以使用圖形化界面配置。如果計數器沒有被設置給指定的事件,錯誤消息就會被顯示。
要通過命令行來為每個可配置的計數器設置事件,使用 opcontrol:
opcontrol --ctrlN-event=<event-name> |
把 N 替換成計數器號碼(從0開始),把 <event-name> 替換成 op_help 中顯示的確切事件名稱。
2.2.1. 抽樣率
默認設置會選擇基於時間的事件設置。它大約會創建每處理器每秒2000個樣品。如果使用了計時器中斷,計時器就被設置成兩幅畫面的最小時間間隔率,而且還不能被用戶設置。如果 cpu_type 不是 timer,每個事件就必須設置了一個抽樣率(sampling rate)。抽樣率是每次抽樣之間發生的事件數量。
在為計數器設置事件時,還可以指定一個抽樣率:
opcontrol --ctrN-event=<event-name> --ctrN-count=<sample-rate> |
把 <sample-rate> 替換成再次抽樣前要等待的事件數量。這個值越小,抽樣的頻率就越高。對於不常發生的事件,你可能需要使用一個較小的值才能捕獲事件實例。
小心 | |
---|---|
在設置抽樣率時務必小心。抽樣率太頻繁會使系統超載,導致系統似乎僵住或者真的僵住了。 |
2.2.2. 單元屏蔽
如果 cpu_type 不是 timer,那麽就可能還需要單元屏蔽(unit masks)來進一步確定事件。
每個事件的單元屏蔽可以使用 op_help 命令列舉。每個單元屏蔽的值都以十六進制格式顯示。要指定一個以上單元屏蔽,十六進制的值必須使用逐位“或”(or)算符來組合。
opcontrol --ctrN-event=<event-name> --ctrN-count=<sample-rate> --ctrN-unit-mask=<value> |
2.3. 分離內核和用戶空間檔案
按照默認設置,每個事件都收集內核模式和用戶模式的信息。要配置 OProfile 在某個指定的計數器中不計數內核模式的事件,執行以下命令(這裏的 N 是計數器號碼):
opcontrol --ctrN-kernel=0 |
執行以下命令來再次啟動計數器的建檔內核模式:
opcontrol --ctrN-kernel=1 |
要配置 OProfile 不計數某個指定計數器的用戶模式的事件,執行以下命令(這裏的 N 是計數器號碼):
opcontrol --ctrN-user=0 |
執行以下命令來再次啟動計數器的建檔用戶模式:
opcontrol --ctrN-user=1 |
當 OProfile 守護進程把檔案數據寫入樣品文件,它可以把內核和庫檔案的數據分成兩個單獨的樣品文件。要配置守護進程寫入樣品文件的方式,以根用戶身份執行以下命令:
opcontrol --separate=<choice> |
<choice> 可以是以下之一:
-
none — 不要分離檔案(默認)
-
library — 為庫生成每個應用程序的檔案
-
kernel — 為內核和內核模塊生成每個應用程序的檔案
-
all — 為庫生成每個應用程序的檔案,為內核和內核模塊生成每個應用程序的檔案
如果 --separate=library 被使用,抽樣文件名在包括可執行文件名稱的同時還包括庫的名稱。
第3節 啟動和停止 OProfile
要使用 OProfile 來開始監視系統,以根用戶身份執行以下命令:
opcontrol --start |
所顯示的輸出和下面相似:
Using log file /var/lib/oprofile/oprofiled.log
Daemon started.
Profiler running. |
/root/.oprofile/daemonrc 中的設置被使用。
OProfile 守護進程 oprofiled 被啟動;它定期把樣品數據寫入 /var/lib/oprofile/samples/ 目錄。該守護進程的日誌位於 /var/lib/oprofile/oprofiled.log。
如果 OProfile 使用不同的配置選項被重新啟動,以前會話中的樣品文件就會被自動備份到/var/lib/oprofile/samples/session-N 目錄中,這裏的 N 是前一次備份會話數量再加1。
Backing up samples file to directory /var/lib/oprofile/samples//session-1
Using log file /var/lib/oprofile/oprofiled.log
Daemon started.
Profiler running. |
要停止建檔器,以根用戶身份執行以下命令:
opcontrol --shutdown |
第4節 保存數據
有時,在指定時間保存樣品會很有用。例如,在給可執行文件建檔的時候,根據不同的輸入數據來收集不同的樣品可能會很有用。如果要監視的事件數量超過了處理器可用的計數器數量,你可以運行多次 OProfile 來收集數據,每次都把樣品數據保存到不同的文件中。
要保存當前的抽樣文件集合,執行以下命令,把 <name> 替換成當前會話中的獨特描述性名稱。
opcontrol --save=<name> |
目錄 /var/lib/oprofile/samples/name/ 被創建,當前的抽樣文件被復制到其中。
第5節 分析數據
OProfile 守護進程 oprofiled 定期收集樣品,並把它們寫入 /var/lib/oprofile/samples/ 目錄。在讀取數據之前,請以根用戶身份執行以下命令來確定所有數據都被寫入這個目錄中了:
opcontrol --dump |
每個樣品文件名稱都基於可執行文件的名稱,使用右括號(})來代替每個正斜線(/)。文件名的結尾是井號(#)和用於該樣品文件的計數器號碼。例如,以下文件包括了計數器0所收集的 /sbin/syslogd 這個可執行文件的樣品數據:
}sbin}syslogd#0 |
一旦抽樣數據被收集,你可以使用以下工具來分析它們:
-
op_time
-
oprofpp
-
op_to_source
-
op_merge
使用這些工具以及被建檔的二進制文件來生成可以進一步被分析的報告。
警告 | |
---|---|
被建檔的可執行文件必須使用這些工具來分析數據。如果它在數據收集後必須被改變,請備份用來創建樣品的可執行文件,以及這些樣品文件。 |
每個可執行文件的樣品都被寫入一個樣品文件。每個動態鏈接庫的樣品也被寫入一個樣品文件。在 OProfile 運行的時候,如果被監視的可執行文件改變了,而且用於這個可執行文件的樣品文件存在,這個現存的樣品文件就會被自動刪除。因此,如果這個樣品文件要被保留,它就必須在可執行文件被新版本替代前和所用的可執行文件一起備份。關於如何備份樣品文件的詳情,請參閱第 43.4 節。
5.1. 使用 op_time
op_time 提供了對所有建檔的可執行文件的總覽。
以下是輸出示例的一部分:
581 0.2949 0.0000 /usr/bin/oprofiled
966 0.4904 0.0000 /usr/sbin/cupsd
1028 0.5218 0.0000 /usr/sbin/irqbalance
1187 0.6026 0.0000 /bin/bash
1480 0.7513 0.0000 /usr/bin/slocate
2039 1.0351 0.0000 /usr/lib/rpm/rpmq
6249 3.1722 0.0000 /usr/X11R6/bin/XFree86
8842 4.4885 0.0000 /bin/sed
31342 15.9103 0.0000 /usr/bin/gdmgreeter
58283 29.5865 0.0000 /no-vmlinux
82853 42.0591 0.0000 /usr/bin/perl |
每個可執行文件都在它自己的行上列出。第一列是為該可執行文件記錄的樣品數量。第二列是樣品和樣品總數的百分比。第三列沒有被使用,第四列是這個可執行文件的名稱。
關於 op_time 命令行選項的列表,請參閱它的說明書頁。例如 -r 選項被用來按照樣品數量的大小給輸出排序;-c 選項在指定計數器號碼時有用。
5.2. 使用 oprofpp
要檢索關於指定可執行文件的詳細信息,使用 oprofpp:
oprofpp <mode> <executable> |
<executable> 必須是到要分析的可執行文件的完整路徑。<mode> 必須是以下之一:
-
-l
-
按照符號列舉樣品數據。例如:以下是運行命令 oprofpp -l /usr/X11R6/bin/XFree86 的部分輸出:
vma samples % symbol name ... 08195d10 4 3.0303 miComputeCompositeClip 080b9180 5 3.78788 Dispatch 080cdce0 5 3.78788 FreeResource 080ce4a0 5 3.78788 LegalNewID 080ce640 5 3.78788 SecurityLookupIDByClass 080dd470 9 6.81818 WaitForSomething 080e1360 12 9.09091 StandardReadRequestFromClient ...
第一列是虛擬內存地址(vma)的起點。第二列是該符號的樣品數量。第三列是該符號的樣品和該可執行文件的總體樣品的百分比。第四列是符號的名稱。
要把輸出按照樣品的數量多少排序(反向),使用 -r 和 -l 選項。
-s <symbol-name>
-
列舉某個符號名稱特有的樣品數據。例如:以下輸出是從命令 oprofpp -s StandardReadRequestFromClient /usr/X11R6/bin/XFree86 中截取的:
vma samples % symbol name 080e1360 12 100 StandardReadRequestFromClient 080e1360 1 8.33333 080e137f 1 8.33333 080e13bb 1 8.33333 080e13f4 1 8.33333 080e13fb 1 8.33333 080e144a 1 8.33333 080e15aa 1 8.33333 080e1668 1 8.33333 080e1803 1 8.33333 080e1873 1 8.33333 080e190a 2 16.6667
第一行是符號/可執行文件組合的摘要。
第一列包括抽樣的虛擬內存地址。第二列是該內存地址的抽樣數量。第三列是該內存地址的樣品和該符號的樣品總數的百分比。
-L
-
按照符號列舉樣品數據,比 -l 更詳細。例如:
vma samples % symbol name 08083630 2 1.51515 xf86Wakeup 08083641 1 50 080836a1 1 50 080b8150 1 0.757576 Ones 080b8179 1 100 080b8fb0 2 1.51515 FlushClientCaches 080b8fb9 1 50 080b8fba 1 50 ...
數據和 -l 選項一樣,只不過,對於每個符號來說,每個所用的虛擬內存地址都被顯示。對於每個虛擬內存地址,樣品數量以及樣品和該符號的樣品數量的百分比也被顯示。
-g <file-name>
-
按照 gprof 格式把輸出生成到文件中。如果生成的文件叫做gmon.out,gprof 就能夠被用來進一步分析數據。詳情請參閱 gprof 的說明書頁。
能夠進一步限定數據的其它選項如下:
-
-f <file-name>
-
使用指定的樣品文件 <file-name>。按照默認設置,/var/lib/oprofile/samples/ 中的樣品文件會被使用。使用這個選項來指定來自前一個會話的樣品文件。
-i <file-name>
-
使用 <file-name> 作為要檢索數據的可執行文件的名稱。
-d
-
給 C++ 符號名稱解碼(demangle)。
-D
-
給 C++ 符號名稱解碼(demangle),簡化 STL 庫的解碼名稱。
--counter <number>
-
為指定計數器收集信息。若沒有指定,默認的計數器是0。
-o
-
每個樣品都顯示源碼中的行號。當可執行文件被編譯時,應該使用 GCC 的 -g 選項。否則,該選項將無法顯示行號。紅帽企業 Linux 的可執行文件默認都沒有使用這個選項編譯。
vma samples % symbol name linear info 0806cbb0 0 0 _start ../sysdeps/i386/elf/start.S:47
-e <symbol-name>
-
在輸出中不包括用逗號分隔的符號列表。
-k
-
顯示包含共享庫的附加列。這個選項只有在配置 OProfile 時指定了 --separate=library 選項,同時又沒有指定 --dump-gprof-file 選項時才會生成結果。
-t <format>
-
按照指定列順序來顯示輸出。該選項不能和 -g 一起使用。
使用以下字母來代表列:
--session <name>
-
指定到會話的完整路徑或相對於 /var/lib/oprofile/samples/ 目錄的目錄。
-p <path-list>
-
指定要分析的可執行文件所在的用逗號分隔的路徑列表。
5.3. 使用 op_to_source
op_to_source 工具試圖匹配特定指令的樣品和源碼中相對應的行。所生成的文件應該在左側列出這些行的樣品。它還會在每個函數的開頭插入註釋,列舉該函數的樣品總數。
要使用這個工具,可執行文件必須使用 GCC 的 -g 選項編譯。紅帽企業 Linux 軟件包沒有默認使用這個選項編譯。
op_to_source 的一般語法是:
op_to_source --source-dir <src-dir> <executable> |
必須指定包含要被分析的源碼和可執行文件的目錄。關於額外命令行選項的列表,請參閱 op_to_source 的說明書頁。
5.4. 使用 op_merge
如果存在多個用於同一可執行文件或庫的樣品文件,樣品文件可以被合並來簡化分析。
例如:要合並 /usr/lib/library-1.2.3.so 庫的文件,以根用戶身份運行以下命令:
op_merge /usr/lib/library-1.2.3.so |
結果文件是 /var/lib/oprofile/samples/}usr}lib}library-1.2.3.so。
要限制樣品文件被合並到指定的計數器,使用 -c 選項,再跟隨一個計數器號碼。
第6節 理解 /dev/profile/ 文件
/dev/oprofile/ 目錄包含 OProfile 的文件系統。使用 cat 命令來顯示這個文件系統的虛擬文件值。例如:以下命令顯示 OProfile 檢測到的處理器類型:
cat /dev/oprofile/cpu_type |
/dev/oprofile/ 中有用於每個計數器的目錄。例如:如果計數器有兩個,其中就會有/dev/oprofile/0/ 和 dev/oprofile/1/ 這兩個目錄。
計數器的每個目錄中都包含以下文件:
-
count — 抽樣間隔
-
enabled — 如果是0,計數器就被關閉,不會為它收集樣品;如果是1,計數器就被開啟,樣品就會為它收集。
-
event — 要監視的事件
-
kernel — 如果是0,當處理器在內核空間時,樣品就不會為這個計數器事件而收集;如果是1,即便處理器在內核空間時,樣品也會被收集。
-
unit_mask — 為計數器啟用的是哪些單元屏蔽
-
user — 如果是0,當處理器在用戶空間時,樣品就不會為計數器事件收集;如果是1,即便處理器在用戶空間時,樣品也會被收集。
這些文件的值可以使用 cat 命令來檢索。例如:
cat /dev/oprofile/0/count |
用法示例
OProfile 不但能夠被開發者用來分析應用程序的性能,它還能夠被系統管理員用來進行系統性能分析。例如:
-
判定哪些應用程序和服務在系統上被使用得最多 — op_time 可以被用來判定應用程序或服務使用了多少處理器時間。如果系統被用於多種服務,但是卻表現不佳,使用最多處理器時間的服務就可以被轉移到專職系統上。
-
判定處理器用量 — CPU_CLK_UNHALTED 事件可以被監視,以便判定某段給定時間內的處理器載量。然後,這個數據就可以被用來判斷另加一個處理器或更快的處理器是否會提高系統性能。
其它資料
本文僅突出討論了一些 OProfile 特性以及配置和使用它的信息。要進一步學習,請參考以下資料。
-
/usr/share/doc/oprofile-0.5.4/oprofile.html — OProfile 手冊
-
oprofile 的說明書頁 — 討論了 opcontrol、oprofpp、op_to_source、op_time、op_merge、和op_help 等命令