此文包含如下內容編程
使用perfmon.exe
跟蹤性能,即性能監視器(Performance Monitor)安全
它是Windows
自帶的一款分析.NET
應用程序的工具,它以圖形的方式來表示從內存管理到JIT性能的方方面面。經過它,咱們也能夠知道咱們應用程序所使用的資源的狀況。服務器
經過 Win + R
的方式,喚出命令提示符工具。在輸入框中輸入 perfmon.exe
(在Windows10裏面,若是在開始菜單出輸入,必定要輸入所有字符,不然敲回車時可能運行的是系統推薦的應用),而後回車便可,以下:網絡
回車後:數據結構
而後,點擊左側欄中【監視工具】下的【性能監視器】, 獲得以下圖形:點擊右側面板中的「綠色加號」,以添加計數器,以下 多線程
能夠看到,.NET Framework
應用程序有許多預約義的對象,包括用於內存管理(.NET CLR Memory
)、互操做性(.NET CLR Interop
)、異常處理(.NET CLR Exceptions
)以及多線程處理(.NET CLR LocksAndThreads
)的計數器等多種工具。框架
點擊列表中項目右邊的「向下箭頭」,能夠查看該性能對象可以支持的計數器dom
單擊要查看的性能計數器。工具
在《選定對象的實例》列表框中,單擊<全部實例>,指定要在全局(也就是在整個系統範圍內)監視CLR的性能計數器。也能夠在《選定對象的實例》列表框中,單擊要監視該應用程序的性能計數器的應用程序的名稱。性能
選擇了對象實例以後,點擊對話框右下方的【肯定】按鈕,既能夠完成添加。
步驟以下圖:
除了以上經過其餘工具的方式外,咱們也能夠在某些狀況下(好比只須要測試某一段代碼的性能的時候)使用代碼的方式來處理,這種狀況下,用代碼或許更加高效。
.NET 爲咱們提供瞭如下類(命名空間System.Diagnostics
)來作這些事情
PerformanceCounter
:表示 Windows NT
性能計數器組件。使用此類可讀取現有的計數器,或自定義更合適的計數器。也能夠向自定義計數器寫入性能數據PerformanceCounterCategory
: 提供與計數器交互的一些方法PerformanceCounterInstaller
:用於指定 PerformanceCounter
組件的安裝程序PerformanceCounterType
:指定PerformanceCounter
計算下一個值(NextValue
)使用的公式示例代碼以下:
using System;
using System.Collections;
using System.Diagnostics;
public class App {
private static PerformanceCounter avgCounter64Sample;
private static PerformanceCounter avgCounter64SampleBase;
public static void Main() {
ArrayList samplesList = new ArrayList();
/// 用於建立目錄/類別
/// 若是不存在,則須要建立,此時不能當即建立計數器,須要過一下子才能使用
if (SetupCategory())
return;
CreateCounters();
CollectSamples(samplesList);
CalculateResults(samplesList);
}
private static bool SetupCategory() {
if (!PerformanceCounterCategory.Exists("AverageCounter64SampleCategory")) {
CounterCreationDataCollection counterDataCollection = new CounterCreationDataCollection();
// 爲目錄添加計數器
CounterCreationData averageCount64 = new CounterCreationData {
CounterType = PerformanceCounterType.AverageCount64,
CounterName = "AverageCounter64Sample"
};
counterDataCollection.Add(averageCount64);
CounterCreationData averageCount64Base = new CounterCreationData {
CounterType = PerformanceCounterType.AverageBase,
CounterName = "AverageCounter64SampleBase"
};
counterDataCollection.Add(averageCount64Base);
// 建立目錄
PerformanceCounterCategory.Create("AverageCounter64SampleCategory",
"Demonstrates usage of the AverageCounter64 performance counter type.",
PerformanceCounterCategoryType.SingleInstance, counterDataCollection);
return true;
} else {
// 目錄已經存在,所以咱們能夠進行後續步驟
return false;
}
}
private static void CreateCounters() {
// 建立計數器
avgCounter64Sample = new PerformanceCounter("AverageCounter64SampleCategory", "AverageCounter64Sample", false);
avgCounter64SampleBase = new PerformanceCounter("AverageCounter64SampleCategory", "AverageCounter64SampleBase", false);
avgCounter64Sample.RawValue = 0;
avgCounter64SampleBase.RawValue = 0;
}
private static void CollectSamples(ArrayList samplesList) {
Random r = new Random(DateTime.Now.Millisecond);
for (int j = 0; j < 100; j++) {
int value = r.Next(1, 10);
Console.Write(j + " = " + value);
avgCounter64Sample.IncrementBy(value);
avgCounter64SampleBase.Increment();
if ((j % 10) == 9) {
OutputSample(avgCounter64Sample.NextSample());
samplesList.Add(avgCounter64Sample.NextSample());
} else
Console.WriteLine();
System.Threading.Thread.Sleep(50);
}
}
private static void CalculateResults(ArrayList samplesList) {
for (int i = 0; i < (samplesList.Count - 1); i++) {
// 輸出樣本信息
OutputSample((CounterSample)samplesList[i]);
OutputSample((CounterSample)samplesList[i + 1]);
// 經過.NET自帶方法,計算計數器的值
float counterValue = CounterSampleCalculator.ComputeCounterValue((CounterSample)samplesList[i], (CounterSample)samplesList[i + 1]);
Console.WriteLine($".NET computed counter value = {counterValue}");
}
}
private static void OutputSample(CounterSample s) {
Console.WriteLine("\r\nSample values - \r\n");
Console.WriteLine($" BaseValue = {s.BaseValue}");
Console.WriteLine($" CounterFrequency = {s.CounterFrequency}");
Console.WriteLine($" CounterTimeStamp = {s.CounterTimeStamp}");
Console.WriteLine($" CounterType = {s.CounterType}");
Console.WriteLine($" RawValue = {s.RawValue}");
Console.WriteLine($" SystemFrequency = {s.SystemFrequency}");
Console.WriteLine($" TimeStamp = {s.TimeStamp}");
Console.WriteLine($" TimeStamp100nSec = {s.TimeStamp100nSec}\r\n");
}
}
複製代碼
這個小節將對這個計數器列表中很經常使用的計數器進行簡要說明
包括如下計數器:
.NET CLR Exceptions
類別包含的計數器提供應用程序引起的異常的相關信息
.NET
異常和轉換爲.NET
異常的非託管異常(例如,從非託管代碼返回的HRESULT
在託管代碼中會被轉換爲異常)。>100
的異常)的指示器。.NET
異常篩選次數。Finally
數量/秒:顯示每秒執行的 finally
塊的數量。特別注意的是,此計數器只計算有異常執行的 finally
塊(即拋出異常以後),不計算正常代碼路徑上的 finally
塊。.NET CLR Interop
(互操做)類別包括的計數器提供應用程序與COM
組件、COM+
服務和外部類型庫交互的相關信息
CCW
數目:它顯示非託管 COM
代碼所引用的託管對象數。CCW
是指正在從非託管 COM
客戶端引用的託管對象的代理COM
互操做調用或P-Invoke
調用期間將參數和返回值從託管代碼封送至非託管代碼(或反之).NET CLR JIT
類別包括的計數器提供的由JIT
編譯相關信息
JIT
編譯的IL
字節數:從應用程序啓動以來,由實時 (JIT
) 編譯器編譯的微軟中間語言 (MSIL
) 字節總數JIT
編譯的方法數:從應用程序啓動以來JI
T 編譯的方法總數。此計數器不包括預先進行
JIT` 編譯的方法JIT
所佔時間百分比:顯示自上次JIT
編譯階段以來JIT
編譯所用運行佔用時間的百分比JIT
每秒編譯的IL
字節數:顯示每秒JIT
編譯的MSIL
字節數JIT
失敗數:自應用程序啓動以來JIT
編譯器編譯失敗的方法的高峯數量.NET CLR Loading
(加載)類別包括的計數器提供已加載的程序集、類和應用程序域的相關信息
AppDomain
數:應用程序中加載的應用程序域數量AppDomain
速率:每秒加載的應用程序域的數量AppDomain
的速率:每秒卸載的應用程序域的數量AppDomain
總數:自應用程序啓動以來已加載的應用程序域的峯值。AppDomain
總數:顯示自應用程序啓動以來卸載的應用程序的峯值。若是應用程序域加載和卸載屢次,則此計數器將在每次卸載應用程序域時遞增。.NET CLR LocksAndThreads
(鎖和線程)類別包括的計數器提供應用程序所使用的託管鎖和託管線程的相關信息
CLR
建立和擁有的,用做託管線程的基礎線程,的本機操做系統線程數。此計數器的值不包括CLR
在其內部操做中使用的線程;它是操做系統進程中線程的子集。CLR
識別的線程數。這些線程與對應的託管線程對象相關聯。CLR
不建立這些線程,但它們在CLR內
至少會運行一次。具備相同線程 ID 的線程不會進行兩次計數CLR
識別的線程總數CLR
識別的線程數.NET CLR Memory
(內存)類別包括的計數器提供GC
的相關信息
1
代堆、第 2
代堆和大型對象堆的總和,即垃圾回收堆上分配的當前內存(以字節爲單位)GC
句柄數:正在使用的垃圾回收句柄的數量。垃圾回收句柄:CLR
和託管環境外部的資源的句柄0
代回收次數:自應用程序啓動以來第0
代對象(即最年輕、最近分配的對象)進行垃圾回收的次數1
代回收次數:自應用程序啓動以來第 1
代對象進行垃圾回收的次數2
代回收次數:自應用程序啓動以來第 2
代對象進行垃圾回收的次數GC
數:因顯式調用 GC.Collect
而執行的垃圾回收次數峯值COM
互操做元數據GC
當前已提交的虛擬內存總量(以字節爲單位)GC
當前保留的虛擬內存量(以字節爲單位)GC
所佔時間百分比:執行上次垃圾回收與執行垃圾回收所用時間的百分比。此計數器一般指示GC
表明應用程序收集和壓縮內存所執行的做業Finalize
)任務後,仍然存在垃圾回收對象數。 若是這些對象具備對其餘對象的引用,則那些對象也會存在,可是不計入此計數器內0
代堆大小:第 0
代中能夠分配的最大字節數;但它不能肯定第 0
代中已分配的字節數0
代提高的字節數/秒:每秒從第 0
代提高到第 1
代的字節數1
代堆大小:第 1
代中的當前字節數(切記,此代中的對象不是直接分配的;這些對象是從之前的第 0
代垃圾回收提高的)1
代提高的字節數/秒:每秒從第 1
代提高到第 2
代的字節數2
代堆大小:第 2
代中的當前字節數,不包括大對象,切記:此代中的對象(不包括大對象)不是直接分配的85000
字節左右的對象視做大對象而且直接在大對象堆中分配;它們不按照級別來提高CLR
進程實例的進程 ID。0
代提高的終止內存:因爲等待終結而從第 0
代提高到第 1
代的內存字節數0
代提高的內存:垃圾回收後仍存在並從第 0
代提高到第 1
代的內存字節數1
代提高的內存:顯示垃圾回收後仍存在並從第 1
代提高到第 2
代的內存字節數.NET CLR Networking
(網絡)類別包括的計數器提供應用程序經過網絡發送和接收的數據的相關信息
AppDomain
中的全部 Socket
對象接收到的字節的總數。此數據包括未定義的任何協議信息的TCP/IP
數據AppDomain
中的全部 Socket
對象已發送的字節的累積總數。此數據包括未定義的任何協議信息的TCP/IP數據AppDomain
中已經鏈接的 Socket
對象的累積總數AppDomain
中的全部 Socket
對象接收到的數據報包的總數AppDomain
中的全部 Socket
對象已發送的數據報包的總數HttpWebRequest
平均生存期:自進程啓動以來,AppDomain
中在上一個間隔中結束的全部HttpWebRequest
對象的平均時間HttpWebRequest
平均排隊時間:自進程啓動以來,AppDomain
中在上一個間隔中結束的全部 HttpWebRequest
對象的平均排隊時間HttpWebRequest
/秒:AppDomain
中每秒建立的 HttpWebRequest
對象的數目HttpWebRequest
/秒:AppDomain
中每秒添加到隊列的 HttpWebRequest
對象的數量HttpWebRequest
/秒:AppDomain
中應用程序每秒調用 Abort
方法的 HttpWebRequest
對象的數量。HttpWebRequest
/秒:AppDomain
中每秒從服務器接收失敗狀態碼的 HttpWebRequest
對象的數量。其餘的網絡性能計數器,如:
網絡性能計數器包含在兩個類別中:
.NET CLR
網絡:.NET Framework 2
上引入且在 .NET Framework 2
及更高版本上受支持的原始性能計數器。.NET CLR
網絡 4:全部上述套接計數器和 .NET Framework 4
及更高版本上受支持的新的性能計數器.NET CLR Security
(安全性)類別包括的計數器提供公共語言運行時針對應用程序執行的安全檢查的相關信息
JIT
) 編譯時的特定權限時,執行連接時代碼訪問安全檢查RT
檢查所佔的時間百分比:自上一次取樣以來執行運行時代碼訪問安全檢查所用運行時間的百分比.NET1.0
版本到4.5
,快速分析程序瓶頸,找出影響效率的代碼。官方網站上有10
天試用版ANTS
性能分析器是一種用於分析.NET
框架支持的用任何語言編寫的應用程序的工具。ANTS
性能分析器能分析全部.NET
應用程序,包括ASP.NET
網絡應用程序、Windows
服務和COM+
應用程序。ANTS
性能分析器能在幾分鐘內識別性能瓶頸,運行很是快速,且響應時,對程序的執行具備最低影響。.NET
內存的優化工具,快速發現內存泄漏問題,而且自動進行內存檢測VS
自帶的性能分析工具:如圖
點擊以後,以下圖
能夠看到,由CPU
、GPU
、內存及性能嚮導四個選項,選擇您想要進行的性能分析,點擊【Start/開始】就能夠了