Windows 性能監視器概述
Windows 性能監視器是一個 Microsoft 管理控制台 (MMC) 管理單元,提供用於分析系統性能的工具。僅從一個單獨的控制台,即可實時監視應用程序和硬件性能,自定義要在日志中收集的數據,定義警報和自動操作的閾值,生成報告以及以各種方式查看過去的性能數據。
啟動 Windows 性能監視器:開始-->運行—>輸入perfmon-->回車
添加-保存計數器設置:
在Windows 2003中,添加完計數器后,直接按Ctrl+S,就能將設置保存為文件的形式,方便下次直接查看,在Win7中來的不那么直接。
開始-->運行-->輸入MMC-->文件-->添加/刪除管理單元-->選擇性能監視器-->添加,然后在性能(本地)中來添加你的計數器,這樣就可以保存了,方便下次查看。
運行截圖:
常用的監視計數器:
對象 |
計數器 |
說明 |
.NET CLR Exceptions | # of Exceps Thrown / sec | 顯示每秒鍾拋出的異常數。這包括 .NET 異常和轉換為 .NET 異常的未受管異常。性能隨此數目的增大而下降。 |
.NET CLR Memory | # Bytes in all Heaps | 顯示其他四個計數器的總和:Gen 0 堆大小、Gen 1 堆大小、Gen 2 堆大小以及大對象堆大小。此計數器表示 GC 堆上當前分配的內存(以字節為單位)。此計數器的值總是比 Process\Private Bytes 的值小,Process\Private Bytes 對進程的 MEM_COMMIT 區域進行計數。Private Bytes minus # Bytes in all Heaps 就是由未受管對象提交的字節數。 用於監視可能的內存泄漏,或者監視受管或未受管對象的內存使用率是否過大。 |
.NET CLR Remoting | Remote Calls/sec | 顯示每秒調用的遠程過程調用的數目。遠程過程調用是對調用方所在應用程序域之外的任何對象的調用。此計數器不是一段時間內的平均值;它顯示最近兩個樣本觀測值的差除以取樣間隔所得的結果。 |
.NET Data Provider for Oracle | NumberOfFreeConnections | 連接池中可用連接的數量。 |
.NET Data Provider for SqlServer | NumberOfFreeConnections | 連接池中可用連接的數量。 |
Process | % Processor Time | 顯示所有進程線程用於執行指令的已用處理器時間的百分比。指令是計算機中的基本執行單位;線程是執行指令的對象;進程是運行程序時創建的對象。此計數中包含了處理某些硬件中斷和陷阱條件時執行的代碼。如果總的處理器時間較長,請使用此計數器確定導致 CPU 利用率很高的進程。 |
Process | Handle Count | 顯示此進程當前打開的句柄的總數。此數字是此進程中的每個線程當前打開的句柄總數。特定進程中句柄計數的增加可能是發生句柄泄漏的錯誤進程的症狀,這將導致服務器上發生性能問題。此問題並不一定會出現,但是在一段時間內對其進行監視以確定是否發生句柄泄漏十分重要。 |
Process | Thread Count | 這個進程中正在活動的線程數目。指令是在處理器中基本的執行單位,線程是指執行指令的對象。每個運行的進程至少有一個線程。 |
SQLServer:General Statistics | User Connections | 顯示sqlserver目前連接的數量,而不是用戶數。如果該計數器超過255,那么你需要將sqlserver的"Maximum Worker Threads" 的配置值設置得比缺省值255高。如果連接的數量超過可用的線程數,那么sqlserver將共享線程,這樣會影響性能。"Maximum Worker Threads"需要設置得比你服務器曾經達到的最大連接數更高。 |
SQLServer:Locks | Number of Deadlocks/sec | 死鎖的數量/秒,死鎖對應用程序的可伸縮性非常有害,並且會導致惡劣的用戶體驗。該計數器的值必須為0。 |
LogicalDisk | % Free Space | % Free Space 是所選邏輯磁盤驅動器上總計可用空間所占的百分比。 |
PhysicalDisk | Disk Read Bytes/sec | 指在讀取操作時從磁盤上傳送字節的速率。 |
PhysicalDisk | Disk Write Bytes/sec | 指在寫入操作時傳送到磁盤上的字節速度。 |
默認狀況下,以下兩個計數器的開關是關着的,需要配置下%WINDIR%\microsoft.net\Framework64\v2.0.50727\CONFIG\machine.config如下開關的(32和64位操作系統的路徑也有不同),否則數據采集不到。
.NET Data Provider for Oracle | NumberOfFreeConnections |
.NET Data Provider for SqlServer | NumberOfFreeConnections |
增加配置,並重啟相應的進程(重啟服務,或者是重啟IIS等)
<system.diagnostics>
<switches>
<add name="ConnectionPoolPerformanceCounterDetail" value="4"/>
</switches>
</system.diagnostics>
用C#采集計數器的數據:
雖然Windows自帶了perfmon工具,並可以生成報告以及以各種方式查看過去的性能數據,但是有時候我們還是定義自己的一些曲線或者報表,那么就需要將性能監視器的數據收集起來,C#提供了PerformanceCounterCategory(性能對象),PerformanceCounter(性能計數器組件)兩個類,提供了操作性能監視器的一些方法,這樣我們就能把數據讀取出來保存到數據庫中或者文件中,可用來隨意產生一些曲線或報表,或者報警Mail等。。。
示例代碼:
using System;
using System.Diagnostics;
using System.Threading;
namespace TestApplication
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(GetPerfCount("Process", "% Processor Time", "_Total"));
Console.WriteLine(GetPerfCount(".NET CLR Memory", "# Bytes in all Heaps", "_Global_"));
Console.WriteLine(GetPerfCount("SQLServer:General Statistics", "User Connections"));
Console.Read();
}
/// <summary>
/// 獲取計數器樣本並為其返回計算所得值--有實例的計數器(對於大多數的計數器)
/// </summary>
/// <param name="categoryName"></param>
/// <param name="counterName"></param>
/// <param name="instance"></param>
/// <returns></returns>
public static float GetPerfCount(string categoryName, string counterName, string instance)
{
PerformanceCounter counter = new PerformanceCounter
{
CategoryName = categoryName,
CounterName = counterName,
InstanceName = instance,
MachineName = ".",
ReadOnly = true
};
counter.NextValue();
Thread.Sleep(200);
try
{
if (counter != null)
{
return counter.NextValue();
}
}
catch (Exception)
{
return -2f;
}
return -1f;
}
/// <summary>
/// 獲取計數器樣本並為其返回計算所得值--無實例的計數器
/// 比如categoryName=SQLServer:General Statistics,counterName=User Connections
/// </summary>
/// <param name="categoryName"></param>
/// <param name="counterName"></param>
/// <returns></returns>
public static float GetPerfCount(string categoryName, string counterName)
{
PerformanceCounter counter = new PerformanceCounter
{
CategoryName = categoryName,
CounterName = counterName
};
counter.NextValue();
Thread.Sleep(200);
try
{
if (counter != null)
{
return counter.NextValue();
}
}
catch (Exception)
{
return -2f;
}
return -1f;
}
}
}