執行緒檢視 (平行處理效能)
這是「並行視覺化檢視」中最詳細、功能最豐富的檢視。 您可以使用這個檢視來識別執行緒是正在執行,還是因為同步處理、I/O 或其他原因而處於封鎖狀態。
在程式碼剖析分析期間,「並行視覺化檢視」會檢查每個應用程式執行緒的所有作業系統內容切換事件。 內容切換發生的原因有很多,例如下列原因:
執行緒因為同步處理原始物件而遭封鎖。
執行緒的配量到期。
執行緒發出封鎖 I/O 要求。
當執行緒停止執行後,[執行緒檢視] 就會為每一個內容切換指派分類。 這些分類會顯示在檢視左下方的圖例中,而且有對應的說明主題可供參閱。 內容切換事件的分類是藉由在執行緒的呼叫堆疊中搜尋已知導致封鎖的 API 所達成。 在找不到呼叫堆疊相符項目的事件中,將會使用 Windows 所提供的等候原因。雖然技術上是正確的,但是 Windows 分類可能是以實作詳細資料為基礎,而非使用者的預期或需求。Windows 將原生輕型讀取器-寫入器鎖定而造成的封鎖狀況報告成 I/O 而非同步處理,就是這樣的例子。不過,透過檢查對應於內容切換事件的呼叫堆疊,您應該能夠在這些情況中識別任何封鎖事件的根本原因。
[執行緒檢視] 也會顯示執行緒之間的相依性。 例如,如果您找到在同步處理物件上遭封鎖的執行緒,這項工具通常會顯示已解除該執行緒封鎖的執行緒,並且會藉由顯示此執行緒在解除前項執行緒封鎖時的呼叫堆疊,讓您知道此執行緒當時正在做什麼。
最後,工具會在執行緒執行當時收集樣本,讓您分析哪一段程式碼在某個執行區段期間由一個或多個執行緒執行。 除了以取樣方式讓您查看執行緒的執行情況之外,此檢視還提供呼叫堆疊樹狀結構的執行分析報表和封鎖報表。
使用方式
[執行緒檢視] 有許多功能。 部分一般用法包括:
識別應用程式的使用者介面 (UI) 在特定執行階段沒有回應的原因。
識別因為同步處理、I/O、分頁錯誤等情形而封鎖所花費的時間長度。
識別對系統上執行之其他處理序造成的干擾程度。
識別平行執行的負載平衡問題。
識別延展性不佳或不存在的原因 (例如,平行應用程式的效能未在系統中有更多邏輯核心可使用時獲得改善的原因)。
了解應用程式中的並行程度,以協助平行化。
了解各個背景工作執行緒彼此之間的相依性,以及執行流程的關鍵路徑。
本節其餘部分將說明推薦的使用模式,讓您在此檢視中獲得更有效提高生產力的經驗。 首先建議您使用 CPU 使用率檢視,將重點放在相關的特定處理序執行階段上。 在您的應用程式中運用情節標記支援,對此處理序會有很大的幫助。 一旦您將範圍縮小到某一個相關的執行時間間隔,就可以選取 [執行緒檢視]。
識別和縮小關切區域
在 [執行緒檢視] 中,您將會看見以 X 軸為時間的時間表檢視。 在程式碼剖析收集的這段期間內,系統中每一個有讀寫動作的實體磁碟裝置,在 Y 軸上都會有兩個 I/O 通道,其中一個代表讀取資料,另一個代表寫入資料。 在磁碟通道下方,會看見處理序中每個執行緒的通道。 一開始執行緒會以其建立的順序排序,因此主應用程式的執行緒會排列在第一個。 您可以使用檢視左上角的排序選項,依照其他準則排序執行緒 (例如,以執行最多執行工作的執行緒當做依據)。
接下來,您可以隱藏未在相關情節中執行任何工作的執行緒,方法是從左欄中選取其名稱,然後按一下工具列中的 [隱藏選取的執行緒] 圖示。 這類執行緒存在的原因很多。 例如,它們可能是閒置執行緒集區的執行緒。 這樣的執行緒通常會遭到完全封鎖 (一般都是因為同步處理所引起)。 您應該從檢視中移除這些執行緒,因為其統計資料可能會使報表摻雜不相干的資訊。
您可以使用 [執行解析] 索引標籤報表,找出可以隱藏的其他執行緒。 若要查看 [執行解析] 圖形,請按一下作用中圖例的 [個別執行緒摘要]。 這個圖形會顯示目前可見的執行時間間隔內,應用程式所含執行緒的執行緒狀態解析。 為了在此圖形中支援延展性,顯示的執行緒數目會有所限制,因此圖形在某些情況下無法顯示應用程式中所有執行緒的資料。 發生這種情況時,最右邊的位置中會顯示省略符號。
現在您已將分析範圍縮小到關切的區域,並且已選取所需的執行緒,因此可以開始執行效能分析。 下列章節將說明可讓您使用的各種不同工具。
執行緒封鎖詳細資料
若要了解執行緒封鎖區域的基本原因,可以讓滑鼠停留在其中一個區域上方,或是選取該區域 (以滑鼠左鍵按一下)。 當您將滑鼠停留在封鎖區域上方時,將會顯示工具提示,其中包含有關封鎖事件的一般資訊,例如分類、導致封鎖的 API (如果有的話)、區域開始時間以及封鎖持續期間。 如果是先佔分類,還會顯示處理序 ID 以及核心停止執行緒時,CPU 上排定之處理序內的執行緒 ID。 您也可以選取所需通道中的封鎖區域,這樣就會在底部視窗中顯示目前的堆疊。 除了工具提示中顯示的內容之外,[目前的堆疊] 索引標籤還會顯示導致封鎖執行緒的呼叫堆疊。 您可以透過檢查呼叫堆疊的方式,判斷執行緒封鎖事件的基本原因。 根據預設,此檢視中會顯示完整的呼叫堆疊,包括使用者和核心堆疊。 當工具能夠識別出問題所在的特定 API 時,就會將呼叫堆疊在該框架以外的部分修剪掉。 如果工具無法判斷導致封鎖發生的根函式呼叫,便會公開整個呼叫堆疊供使用者檢查並做出判斷。
當執行路徑造成多個封鎖事件時,通常就會有這種情況。 因此,了解呼叫堆疊所構成的累積封鎖延遲也相當有價值。 基於這個目的,我們為每一個封鎖分類提供以呼叫樹狀圖呈現的程式碼剖析報表。 您可以在左側選取其中一個暫停分類圖例項目,以檢視程式碼剖析。 當您調整應用程式時,這些報表可讓您迅速排出應投入時間效能的優先順序。
執行緒之間的相依性
「並行視覺化檢視」會顯示處理序內封鎖執行緒之間的相依性。 若要判斷是哪一個執行緒的動作解除了相關執行緒的封鎖,請按一下相關的封鎖區段。 如果工具可以判斷導致解除封鎖的執行緒,就會繪出直線,將封鎖區段後面的執行區段連到其他執行緒。 這條線指出別的執行緒解除封鎖所選執行緒的方式。 此外,還會有相關的呼叫堆疊填入 [解除封鎖堆疊] 索引標籤。 因此,您可以很快地識別遭封鎖的執行緒、得知該執行緒當時嘗試的動作,進而了解其終究得以執行的原因。
執行緒執行詳細資料
通常,判斷執行緒在應用程式執行當時正在執行的程式碼會十分有用。 這些區域會在時間表圖形中顯示為綠色區段。 有兩項功能有助於進行這項作業。
首先,當您按一下時間表中的執行區段時,我們會嘗試找出最接近的樣本分析呼叫堆疊。 若成功的話,會在執行區塊中取樣的位置上方顯示黑色的插入號,並且在 [目前的堆疊] 索引標籤中顯示呼叫堆疊本身。 您可以在執行區段中的其他位置按一下,選取其他樣本。 不過,有時候可能找不到樣本。 這通常是因為我們收集樣本分析的時間為一毫秒的緣故。 例如,當執行區段長度不到一毫秒時,可能就無法收集到任何呼叫堆疊。 雖然取樣頻率是無法變更的,但是一毫秒足以在精確度和執行額外負荷之間取得平衡。
其次,執行取樣分析報表及其呼叫樹狀圖檢視是一項重要的功能,有助於了解執行時間用在何處。 您可以按一下作用中圖例的 [執行] 項目來存取此功能。 執行分析會為目前檢視中所有啟用的 (未隱藏的) 執行緒提供樣本報表,而這些執行緒是由視窗中的時間範圍所篩選的。
時間表圖形
時間表圖形會顯示處理序內所有執行緒及主機電腦上所有實體磁碟裝置的活動。 您可以透過拖曳滑鼠指標、使用視窗工具列中的縮放滑桿,或是按住 CTRL 同時轉動滑鼠滾輪的方式放大時間表。 將滑鼠停留在其中一個水平列 (或區段) 上方,即可查看執行緒上該點的分類、開始時間和持續期間。 按一下其中一個區段,即可在 [目前的堆疊] 索引標籤上的畫面下半部看見呼叫堆疊。
在時間表圖形中,色彩表示任何指定時間的執行緒狀態。 例如,綠色區段表示執行緒正在執行、紅色區段表示因同步處理遭封鎖、黃色區段表示已遭先佔,而紫色區段則表示正忙著處理裝置 I/O。 此檢視適合在一群參與平行迴圈或並行工作的執行緒中,用來檢查其工作負載是否平衡。 如果一個或多個執行緒比其他執行緒使用更長的時間才完成,則可能表示工作負載不平衡,而且可透過在執行緒之間更平均地分散工作來改善程式的效能。
您也可以使用時間表圖形檢查執行緒之間的相依性,以及封鎖和遭到封鎖之執行緒的時間先後關聯性。 查看時間表上任何一點的垂直切割,便可得知該時間點當時有多少個執行緒正在執行。 如果當時只有一個綠色 (正在執行) 的執行緒,即表示應用程式並未妥善利用系統上可用的並行。 您可以按一下工具列中的向上和向下按鈕來排序和移動個別執行緒,也可以使用 [隱藏執行緒] 按鈕來隱藏不重要的執行緒。
程式碼剖析報告
在時間表圖形下方是作用中圖例和索引標籤式視窗,其中包含數份報表。 當 [執行緒檢視] 因縮放、捲動、隱藏或解除隱藏執行緒而變更時,程式碼剖析報表會自動隨著更新。 如果追蹤的規模較大,報表視窗將會在計算更新的報表時變成暗灰色。 每一份報表都會有兩項篩選調整:[減少雜訊] 和 [Just My Code]。 [減少雜訊] 可協助篩除呼叫樹狀圖中需時甚短的不重要項目。 預設值為 2%,但是可以調整成介於 0% 到 99% 之間的任何值。 [Just My Code] 核取方塊可讓您篩除或檢視不屬於自己的呼叫樹狀圖項目。 下一節將詳細說明可用的報表。
程式碼剖析報表
透過此索引標籤可存取目前的程式碼剖析報表。 實際顯示的程式碼剖析報表,是根據您在作用中圖例上按一下所選取的項目而定。 下一節將列出以 [執行] 開頭的可用程式碼剖析報表。
目前的堆疊
此索引標籤會顯示詳細資料圖形中,所選取執行緒區段的呼叫堆疊。 呼叫堆疊會加以修剪並著重在與程式直接相關的活動。 在選取範圍視窗內,可立即看見 [目前執行中] 執行緒資訊。
解除封鎖堆疊
按一下 [解除封鎖堆疊],即可查看哪個執行緒在哪一行程式碼上解除封鎖此執行緒。
執行
執行分析報表會顯示詳細的表格,以及每一個執行緒在各種不同狀態 (例如執行、I/O 和記憶體管理) 中所花費的時間百分比。
在所需的任何呼叫樹狀圖項目旁邊按一下樹狀目錄控制項,即可向下鑽研並找出時間耗用在執行的那一行程式碼。 一旦找到所需的呼叫樹狀圖項目後,以滑鼠右鍵按一下內容功能表上的 [檢視原始檔] 和 [檢視呼叫位置] 項目。 按一下 [檢視原始檔] 會找出至原始檔的該行,而按一下 [檢視呼叫位置] 則會找出呼叫此執行的程式碼行。 如果只存在一個呼叫位置,按一下就會找出此呼叫位置的程式碼行並反白顯示。 如果存在多個呼叫位置,便會出現對話方塊,讓使用者可以從中選取一個項目。 按一下 [移至原始檔] 按鈕就會找出呼叫位置並反白顯示。 選取並找出含有最多執行個體、耗用最多時間或兩者皆有之呼叫位置的原始程式碼,通常最有幫助。 如需詳細資訊,請參閱執行分析報表。
同步處理
同步處理報表會顯示哪些呼叫引發同步處理封鎖,以及每一個呼叫堆疊的彙總封鎖時間。 您可以使用此資訊識別並調查關切的區域。
在所需的任何呼叫樹狀圖項目旁邊按一下樹狀目錄控制項,即可向下鑽研並找出時間耗用在同步處理的那一行程式碼。 一旦找到所需的呼叫樹狀圖項目後,以滑鼠右鍵按一下內容功能表上的 [檢視原始檔] 和 [檢視呼叫位置] 項目。 按一下 [檢視原始檔] 會找出至原始檔的該行,而按一下 [檢視呼叫位置] 則會找出呼叫此執行的程式碼行。 如果只存在一個呼叫位置,按一下就會連接至此呼叫位置的程式碼行並反白顯示。 如果存在多個呼叫位置,便會出現對話方塊,讓使用者可以從中選取一個項目。 按一下 [移至原始檔] 按鈕,會找出呼叫位置,並以反白顯示。 選取並連接到含有最多執行個體、耗用最多時間或兩者皆有之呼叫位置的原始程式碼,通常最有幫助。 如需詳細資訊,請參閱同步處理時間。
I/O
I/O 報表會顯示哪些呼叫引發 I/O 封鎖,以及每一個呼叫堆疊的彙總封鎖時間。 您可以使用此資訊識別並調查關切的區域。
按一下任何要處理的呼叫堆疊旁邊的樹狀目錄控制項向下鑽研,便可尋找將時間花在 I/O 的程式碼。 一旦找到所需的呼叫樹狀圖項目後,以滑鼠右鍵按一下內容功能表上的 [檢視原始檔] 和 [檢視呼叫位置] 項目。 按一下 [檢視原始檔] 會找出至原始檔的該行,而按一下 [檢視呼叫位置] 則會找出呼叫此執行的程式碼行。 如果只存在一個呼叫位置,按一下就會連接至此呼叫位置的程式碼行並反白顯示。 如果存在多個呼叫位置,便會出現對話方塊,讓使用者可以從中選取一個項目。 按一下 [移至原始檔] 按鈕就會找出呼叫位置並反白顯示。 選取並連接到含有最多執行個體、耗用最多時間或兩者皆有之呼叫位置的原始程式碼,通常最有幫助。 如需詳細資訊,請參閱 I/O 時間 (執行緒檢視)。
睡眠
睡眠報表會顯示哪些呼叫引發睡眠封鎖,以及每一個呼叫堆疊的彙總封鎖時間。 您可以使用此資訊識別並調查關切的區域。
按一下任何要處理的呼叫堆疊旁邊的樹狀目錄控制項向下鑽研,便可尋找將時間花在睡眠的程式碼。 一旦找到所需的呼叫樹狀圖項目後,以滑鼠右鍵按一下內容功能表上的 [檢視原始檔] 和 [檢視呼叫位置] 項目。 按一下 [檢視原始檔] 會找出至原始檔的該行,而按一下 [檢視呼叫位置] 則會找出呼叫此執行的程式碼行。 如果只有一個呼叫位置,按一下會連接到此呼叫位置的程式碼行,並以反白顯示。 如果有多個呼叫位置,則會出現對話方塊,讓使用者可以從中選取一個項目。 按一下 [移至原始檔] 按鈕,會找出呼叫位置,並以反白顯示。 選取並連接到含有最多執行個體、耗用最多時間或兩者皆有之呼叫位置的原始程式碼,通常最有幫助。 如需詳細資訊,請參閱睡眠時間。
分頁
先佔報表會顯示發生先佔封鎖的呼叫,以及每一個呼叫堆疊的彙總封鎖時間。 您可以使用此資訊識別並調查關切的區域。 相對於其他報表,這份封鎖報表比較沒有需要追究之處,因為先佔通常是作業系統對處理序進行的強制行為,而非程式碼所造成。 它會顯示發生何種先佔、發生的位置,以及您的流程處於指定之先佔狀態的時間有多長。
在所需的任何呼叫樹狀圖項目旁邊按一下樹狀目錄控制項,即可向下鑽研並找出時間耗用在先佔的那一行程式碼。 一旦找到所需的呼叫樹狀圖項目後,以滑鼠右鍵按一下內容功能表上的 [檢視原始檔] 和 [檢視呼叫位置] 項目。 按一下 [檢視原始檔] 會巡覽至原始檔的該行,而按一下 [檢視呼叫位置] 則會巡覽至呼叫此執行的程式碼行。 如果只有一個呼叫位置可用,按一下就會直接巡覽至此呼叫位置的程式碼並反白顯示。 如果有多個呼叫位置,則會出現對話方塊,讓使用者可以從中選取一個項目。 按一下 [移至原始檔] 按鈕,會找出呼叫位置,並以反白顯示。 選取並連接到含有最多執行個體、耗用最多時間或兩者皆有之呼叫位置的原始程式碼,通常最有幫助。 如需詳細資訊,請參閱記憶體管理時間。
先佔
先佔報表會顯示發生先佔封鎖的呼叫,以及每一個呼叫堆疊的彙總封鎖時間。 您可以使用此資訊識別並調查關切的區域。 相對於其他報表,這份封鎖報表比較沒有需要追究之處,因為先佔通常是作業系統對處理序進行的強制行為,而非程式碼所造成。 它會顯示發生何種先佔、發生的位置,以及您的流程處於指定之先佔狀態的時間有多長。
在所需的任何呼叫樹狀圖項目旁邊按一下樹狀目錄控制項,即可向下鑽研並找出已將時間耗在先佔的那一行程式碼。 一旦找到所需的呼叫樹狀圖項目後,以滑鼠右鍵按一下內容功能表上的 [檢視原始檔] 和 [檢視呼叫位置] 項目。 按一下 [檢視原始檔] 會巡覽至原始檔的該行,而按一下 [檢視呼叫位置] 則會巡覽至呼叫此執行的程式碼行。 如果只有一個呼叫位置可用,按一下就會直接巡覽至此呼叫位置的程式碼並反白顯示。 如果有多個呼叫位置,則會出現對話方塊,讓使用者可以從中選取一個項目。 按一下 [移至原始檔] 按鈕,會找出呼叫位置,並以反白顯示。 選取並連接到含有最多執行個體、耗用最多時間或兩者皆有之呼叫位置的原始程式碼,通常最有幫助。 如需詳細資訊,請參閱先佔時間。
UI 處理
UI 處理報表會顯示哪些呼叫引發 UI 處理封鎖,以及每一個呼叫堆疊的彙總封鎖時間。 您可以使用此資訊識別並調查關切的區域。
在所需的任何呼叫樹狀圖項目旁邊按一下樹狀目錄控制項,即可向下鑽研並找出時間耗用在 UI 處理的那一行程式碼。 一旦找到所需的呼叫樹狀圖項目後,以滑鼠右鍵按一下內容功能表上的 [檢視原始檔] 和 [檢視呼叫位置] 項目。 按一下 [檢視原始檔] 會找出至原始檔的該行,而按一下 [檢視呼叫位置] 則會找出呼叫此執行的程式碼行。 如果只有一個呼叫位置,按一下會連接到此呼叫位置的程式碼行,並以反白顯示。 如果有多個呼叫位置,則會出現對話方塊,讓使用者可以從中選取一個項目。 按一下 [移至原始檔] 按鈕,會找出呼叫位置,並以反白顯示。 選取並連接到含有最多執行個體、耗用最多時間或兩者皆有之呼叫位置的原始程式碼,通常最有幫助。 如需詳細資訊,請參閱 UI 處理時間。
個別執行緒摘要
此索引標籤會顯示每個執行緒耗用在每一種狀態 (例如執行中、遭封鎖和 I/O) 的總時間,並以不同的顏色區分各個資料行。 資料行底部會加上標籤。 在預設縮放層級中,主執行緒位於最左邊的資料行。 當您調整詳細資料圖形中的縮放層級時,索引標籤報表將會自動更新以反映新的時間刻度。 為了在此圖形中支援延展性,顯示的執行緒數目會有所限制。 因此,圖形在某些情況下可能無法顯示應用程式中所有執行緒的資料,但是會在最右邊的位置中以省略符號來表示這項限制。 如果此圖形沒有顯示您希望看到的執行緒,您可以隱藏比較不重要的執行緒,直到所需的執行緒出現在圖形中為止。 如需詳細資訊,請參閱個別執行緒摘要報表。
檔案作業
此索引標籤會顯示磁碟 I/O 是由哪些執行緒引起的,以及這些執行緒存取了哪些檔案。 這包括載入的 DLL、已讀取的位元組數目及其他資訊。 這份報表可用來評估執行期間存取檔案所耗用的時間,尤其是當您的處理序似乎受限於 I/O 時特別有用。 如需詳細資訊,請參閱檔案作業報表 (執行緒檢視)。