本系列文章的第 3 部分重點關(guān)注中央處理單元 (CPU) 性能優(yōu)化中鮮為人知的方面:控制線程使用和 CPU 綁定。本文介紹了一些關(guān)鍵的工具和實用程序,您可以使用它們來分析線程和管理進(jìn)程。
本系列的三篇文章重點關(guān)注中央處理單元 (CPU) 性能和監(jiān)視的方方面面。本系列的第一部分概述了如何高效地監(jiān)視 CPU,討論了進(jìn)行性能優(yōu)化的方法,并且給出了可能對性能產(chǎn)生積極或消極影響的一些注意事項,還介紹了一些相關(guān)的命令。本系列的第二部分則更關(guān)注于實際的 CPU 系統(tǒng)監(jiān)視、對趨勢和結(jié)果進(jìn)行分析的細(xì)節(jié)內(nèi)容。本系列的第三部分重點關(guān)注于主動控制線程使用和優(yōu)化 CPU 以實現(xiàn)性能最大化的其他方法。在本系列文章中,我還將詳細(xì)說明 AIX? CPU 性能優(yōu)化和監(jiān)視方面的各種最佳實踐。
本文的內(nèi)容包括線程、進(jìn)程和 CPU 綁定。本文還討論了如何使用在前面幾期文章中介紹的一些工具,以便對您的系統(tǒng)進(jìn)行更改。同時,本文還介紹了 AIX Version 5.3 中用于優(yōu)化 CPU 調(diào)度程序的最重要的命令以及線程綁定的各種方法。
初級的管理員可能認(rèn)為進(jìn)程管理只不過就是監(jiān)視活動的進(jìn)程、終止失控的或僵死的進(jìn)程。您將會發(fā)現(xiàn),進(jìn)程管理并不僅僅只是使用 kill 命令或者甚至 nice 命令。在繼續(xù)學(xué)習(xí)后面的內(nèi)容之前,需要弄清楚一個基本的問題,即進(jìn)程與線程之間存在怎樣的關(guān)系。其答案非常的簡單。進(jìn)程是 AIX 用于控制系統(tǒng)資源使用的實體,而線程則用于控制使用的時間,因為每個內(nèi)核線程都是一個單獨的順序控制流。每個進(jìn)程由一個或多個線程組成。您可以根據(jù)實際情況來控制線程的使用。要做到這一點,您需要了解一些相關(guān)的工具,這些工具允許您使用線程來提高 CPU 的性能,而這正是本系列文章中最后一部分內(nèi)容的研究范圍。
在這個部分中,我將介紹一些相關(guān)的工具和命令,它們可以幫助您監(jiān)視和分析線程的使用。盡管在 AIX Version 4 中就引入了通過線程的使用來控制處理器使用時間的方法,但是直到 AIX 5L? 才真正提供了幫助您監(jiān)視和分析線程使用的系統(tǒng)管理工具。其中一種工具是 Procmon,在 AIX Version 5.3 中引入了該工具。
Procmon 可以顯示進(jìn)程的列表(當(dāng)您的系統(tǒng)變化時,該列表也將動態(tài)地變化),通過這個列表,您可以收集有關(guān)系統(tǒng)中正在運行的進(jìn)程的信息。與其他監(jiān)視工具相比,其獨特之處在于,它允許您運行各種命令以簡化進(jìn)程和線程的管理。它能夠收集的、與性能優(yōu)化相關(guān)的一些關(guān)鍵信息包括:
某個進(jìn)程實際使用的 CPU 時間
某個進(jìn)程的內(nèi)存和 I/O 用量
進(jìn)程的 nice(優(yōu)先級調(diào)整參數(shù))值及其優(yōu)先級
您甚至可以 kill 任務(wù)(終止任務(wù)),并且動態(tài)地 renice 它們(調(diào)整其優(yōu)先級)。
圖 1 給出了關(guān)于整體性能的圖形表示。要啟動 Performance Workbench Platform,可以使用: # perfwb。
其中還包括一個進(jìn)程表視圖,用于在經(jīng)過排序的表格中顯示線程列表。您只需選擇 Show threads metrics 即可(請參見
圖 2)。
其他的一些菜單允許您 kill 進(jìn)程(終止進(jìn)程)或者 renice 它們(重新調(diào)整進(jìn)程的優(yōu)先級),請參見
圖 3。
那么,nice 究竟是什么呢?您可以使用 nice 命令調(diào)整給定進(jìn)程的優(yōu)先級。所有進(jìn)程的缺省值都為 20。使用 renice 命令(通過 Procmon 或者命令行)可以使得系統(tǒng)為給定的進(jìn)程分配一個更高的或者更低的優(yōu)先級。在進(jìn)行該操作時,您實際上通過更改進(jìn)程的 nice 值,從而更改了線程優(yōu)先級的值(缺省值為 40)。
如果您在運行 ps 命令時使用了 -l 標(biāo)志,那么您將看到具體的 nice 信息(請參見
清單 1)。
# ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 200001 A 0 12972 45770 0 60 20 dea6 764 pts/1 0:00 ksh 200001 A 0 33816 12972 3 61 20 36168 440 pts/1 0:00 ps 240001 A 207 45770 40374 0 60 20 258ec 744 pts/1 0:00 ksh
讓我們通過 nice 啟動一個新的 ksh,更改進(jìn)程的優(yōu)先級:# nice --10 ksh(請參見
清單 2)。
當(dāng)您再次使用 ps 查看進(jìn)程表時,您將看到,對于這個進(jìn)程以及它通過 fork 系統(tǒng)調(diào)用創(chuàng)建的子進(jìn)程,它們的優(yōu)先級都不再是缺省值。
# ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 200001 A 0 12972 45770 0 60 20 dea6 764 pts/1 0:00 ksh 200001 A 0 17246 12972 0 50 10 68a1f 748 pts/1 0:00 ksh 200001 A 0 18450 17246 1 50 10 51bb1 380 pts/1 0:00 ps 240001 A 207 45770 40374 0 60 20 258ec 744 pts/1 0:00 ksh
您還可以使用 renice 命令(前面在介紹 Procmon 的
圖 3 中對該命令進(jìn)行了說明),以便動態(tài)地為一個運行的進(jìn)程重新分配優(yōu)先級。
讓我們回到 ps。如果您希望更詳細(xì)地查看相關(guān)的線程,那么您可以使用 -mo 標(biāo)志(請參見
清單 3)。
# ps -mo THREAD USER PID PPID TID ST CP PRI SC WCHAN F TT BND COMMAND root 12800 45770 - A 0 60 1 - 200001 pts/1 - -ksh - - - 56759 S 0 60 1 - 10400 - - - root 44648 12800 - A 1 60 1 - 200001 pts/1 - ps -mo THREAD - - - 64905 R 1 60 1 - 0 - - - kmilberg 45770 40374 - A 0 60 1 - 240001 pts/1 - -ksh - - - 54005 S 0 60 1 - 10400 - - -
盡管大多數(shù)管理員通常僅在進(jìn)行 ps -ef 操作時使用 ps,但是如果您更仔細(xì)地研究它的特性,那么您將會了解到更多關(guān)于 ps 的內(nèi)容。
您已經(jīng)了解了如何更改進(jìn)程的優(yōu)先級,那么對于線程又該如何操作呢?這部分內(nèi)容介紹了如何更改用于計算每個線程優(yōu)先級值的 CPU 調(diào)度參數(shù)。您可以使用 schedo(在 AIX Version 5.2 及更早的版本中是 schedune)來完成這項工作。
首先,您需要確保擁有下面的文件集(請參見
清單 4)。
# lslpp -lI bos.perf.tune Fileset Level State Description ---------------------------------------------------------------------------- Path: /usr/lib/objrepos bos.perf.tune 5.2.0.10 COMMITTED Performance Tuning Support Path: /etc/objrepos bos.perf.tune 5.2.0.10 COMMITTED Performance Tuning Support
現(xiàn)在,讓我們報告所有的 CPU 參數(shù),如
清單 5 所示。
# schedo -a %usDelta = 100 affinity_lim = 7 big_tick_size = 1 fixed_pri_global = 0 force_grq = 0 idle_migration_barrier = 4 maxspin = 16384 pacefork = 10 sched_D = 16 sched_R = 16 timeslice = 1 v_exempt_secs = 2 v_min_process = 2 v_repage_hi = 0 v_repage_proc = 4 v_sec_wait = 1
首先從 fixed_pri_global 開始進(jìn)行分析。它的缺省設(shè)置為 0。當(dāng) CPU 準(zhǔn)備分派線程時,它會先檢查全局運行隊列,然后再檢查其他隊列。當(dāng)線程在 CPU 上的時間片結(jié)束之后,它將被重新放回到這個隊列中。這可以幫助維護(hù)處理器的關(guān)聯(lián)性(稍后我將介紹這部分內(nèi)容)。要提高整體的線程性能,您可以將名為 RT_GRQ 的環(huán)境變量設(shè)置為 ON。這樣一來,就會自動地將線程放入到全局運行隊列中。如果您將缺省值從 0 更改為 1,那么所有固定優(yōu)先級的線程都將放入到這個運行隊列中。您可以執(zhí)行下面的命令將缺省值從 0 更改為 1: #schedo -o fix_pri_global=1。
讓我們再來討論一下線程。用戶進(jìn)程的實際優(yōu)先級會隨著時間發(fā)生變化,這取決于該進(jìn)程最近所使用的 CPU 時間。您需要查看的參數(shù)包括 sched_R 和 sched_D。這兩個參數(shù)值的單位都是 1/32 秒,并且它們的缺省值都為 16。而且,對于剛創(chuàng)建的線程,其 CPU 值為 0。隨著線程在 CPU 上執(zhí)行時間的增加,其 CPU 使用時間將會遞增。實際上,調(diào)度程序使用下面的公式來計算 CPU 使用時間: CPU usage = CPU usage*(D/32)。
在這個示例中,如果 D 參數(shù)設(shè)置為 32,那么線程的 CPU 使用時間將不會衰減,而該參數(shù)的缺省值為 16,這樣就允許 CPU 使用時間隨著時間的推移而衰減,從而使其獲得更多的在 CPU 上執(zhí)行的時間。
每個 CPU 都有一個專門的運行隊列。運行隊列是由運行線程所組成的列表,按照線程優(yōu)先級的值進(jìn)行排序。一共有 256 種線程優(yōu)先級(從 0 到 255)。還有一個附加的全局運行隊列,其中放的是新的線程。
Schedo 通常用于更改調(diào)度程序時間片的長度。要更改時間片,可以使用 schedo -o timeslice=value 選項。增加時間片的長度可以提高系統(tǒng)吞吐量,因為減少了上下文的切換。在進(jìn)行這種更改之前,請確保反復(fù)地運行 vmstat 以確定系統(tǒng)中確實正在進(jìn)行大量的上下文切換工作。
在這部分內(nèi)容中,我將介紹有關(guān) CPU 綁定的主題,即允許進(jìn)程在特定的處理器上運行。這個術(shù)語本身可稱為處理器關(guān)聯(lián)。處理器關(guān)聯(lián)有許多用途,其中一些甚至可以在調(diào)試的過程中使用。例如,您可以將線程綁定到給定的處理器,以找出導(dǎo)致某個掛起程序的根源。通常,在嘗試將程序分散到多處理機系統(tǒng)(例如 SMP 系統(tǒng))中時,會使用到處理器關(guān)聯(lián)。您所使用的命令是 bindprocessor 命令。假定啟用了同步多線程 (SMT),這是缺省的行為,那么在運行 bindprocessor 命令時,會將物理處理器的每個硬件線程作為單獨的處理器列舉出來。在 POWER5 芯片中,每個處理器中有兩個硬件線程。對于共享的處理器邏輯分區(qū) (LPAR),使用這個命令可以綁定到虛擬 CPU,所以您必須非常小心,因為它可能會導(dǎo)致預(yù)先安排運行于特定 CPU 的應(yīng)用程序出現(xiàn)問題。讓我們首先檢查一下是否啟用了 SMT(請參見
清單 6)。
# smtctl SMT is currently enabled.
清單 7 顯示了一個啟用了 SMT 的雙向系統(tǒng)的輸出。
# bindprocessor -q The available processors are: 0 1 2 3
如果您希望將一個進(jìn)程綁定到某個特定的 CPU,非常簡單,可以執(zhí)行下面的命令: # bindprocessor 12741 2
有時候,會很自然地出現(xiàn)處理器關(guān)聯(lián)的情況。當(dāng)某個線程在一個 CPU 上運行并發(fā)生了中斷,通常會將它放回到相同的 CPU 上運行,因為這個處理器的緩存中仍然保存了屬于該線程的相關(guān)信息。如果將其分派到另一個 CPU,它可能不得不從 RAM 中獲取相關(guān)信息,而這將極大地降低處理的速度。
您還可以使用子例程來綁定線程,盡管我在進(jìn)行這種工作時會倍加小心。它所執(zhí)行的操作是將一個進(jìn)程中所有的內(nèi)核線程綁定到某個處理器,這樣做將強制這些線程運行于某個特定的處理器中,直到解除對它們的綁定。
編程中使用的另一個重要線程命令是 gprof。gprof 命令為您所編譯的程序(可能是用 C、Pascal、FORTRAN、或者甚至是 COBOL 編寫的程序)產(chǎn)生一個執(zhí)行概要。gprof 可以報告您的程序中所有子例程的流程控制,并為您提供每個子例程所使用的 CPU 時間。在對進(jìn)程如何使用 CPU 資源進(jìn)行故障診斷時,這是非常有用的。相關(guān)的數(shù)據(jù)來自于概要文件 (gmon.out)。您可以使用 gprof 對您的程序進(jìn)行概要分析,并確定哪些函數(shù)正在使用 CPU。概要數(shù)據(jù)來自于調(diào)用關(guān)系圖概要文件(缺省情況下是 gmon.out)。那么,在 AIX Version 5.3 中有何不同呢?因為 AIX Version 5.3 允許輸出文件的概要具有用戶指定的名稱(通過設(shè)置特殊的環(huán)境變量),所以,為線程提供了附加的概要支持和選項,而這些都會影響所收集的概要數(shù)據(jù)的類型。
在本文中,我介紹了控制線程使用和 CPU 綁定的重要性。您了解了一些用于分析線程和管理進(jìn)程的、關(guān)鍵的工具和實用程序。而且,您使用 schedo 對內(nèi)核進(jìn)行了優(yōu)化,了解了與處理器關(guān)聯(lián)有關(guān)的所有內(nèi)容,并掌握了如何綁定 CPU。本系列文章主要介紹關(guān)于 CPU 監(jiān)視的內(nèi)容,共由三篇文章組成,首先引入了優(yōu)化的概念,然后介紹了監(jiān)視和數(shù)據(jù)收集,最后以系統(tǒng)優(yōu)化和管理作為結(jié)束。盡管大多數(shù)的讀者可能對內(nèi)存子系統(tǒng)的優(yōu)化更加熟悉,但是我希望通過本系列文章說明 CPU 監(jiān)視和優(yōu)化的重要性。