.Net最佳實踐3:使用性能計數器收集性能數據


本文值得閱讀嗎?

本文討論我們如何使用性能計數器從應用程序收集數據。我們將先了解的基本知識,然后我們將看到一個簡單的示例,我們將從中收集一些性能數據。

clip_image001

 

 

介紹: - 我的應用程序的性能是最好的,像火箭

讓我們這篇文章從一個客戶和開發人員之間的簡短交談開始。

 

場景1

客戶:- 你們的應用程序的性能怎么樣?
主觀的開發者:- Well,它真的很快,它是最好的... huuh aaa ooh,它就像火箭一樣。

 

場景2

客戶:- 你們的應用程序的性能怎么樣?

量化的開發者:- 使用2 GB RAM,xyz處理器和20000客戶記錄的情況下,客戶屏幕在20秒內加載完成。

 

我肯定比第一個開發的第二個開發者看起來更有前途的。在這篇文章中,我們將探討我們如何使用性能計數器來測量應用程序的性能。讓我們開始計數1,2,3,4 ......

 

歡迎下載我的免費的500 Q&A電子書,內容涉及NET,ASP.NET,SQL Server,WCF,WPF,WWF@ http://www.questpond.com . (譯者:作者在原文中做了一些廣告,作為對他勞動成果的尊重,我將照原文翻譯)


clip_image002

 

感謝Javier和Michael

我真的沒有才智來寫一些關於性能計數器的東西。但閱讀下面的文章中,我能對付着寫一些東西了。因此,首先請允許我感謝這些人,然后我們再繼續本文。

感謝Javier Canillas創建了performance counter helper,它確實簡化了很多代碼http://perfmoncounterhelper.codeplex.com/

感謝Michael Groeger精彩的文章,我從你的文章中摘取了計數器創建的代碼http://www.codeproject.com/KB/dotnet/perfcounter.aspx

我也從以下文章中摘取了不少內容:

http://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter.aspx

 

歸根結底,它們是:計數,計算(calculate)和顯示

任何性能評估的工作無外乎計數,計算和顯示。例如,如果你要計算在內存中每秒處理多少分頁,我們首先我們需要對處理的頁面的數量和其間流逝的時間(多少秒)進行計數。一旦我們完成計數,我們就需要進行計算,如用分頁數除以秒數。最后,我們需要顯示我們的性能數據。

clip_image003

 

現在,我們知道這是一個3步驟的過程,即計數,計算和顯示。計數的部分由應用程序來完成。因此,在計數階段應用程序需要提供數據。請注意,數據不會被性能計數器自動檢測到,而需要應用程序提供一些幫助。而計算和顯示由性能計數器和監視器完成。

clip_image004

 

性能計數器不是魔術師

如果應用程序不提供計數器數據,性能計數器無法僅憑自身去衡量應用程序性能。性能計數器需要應用程序來提供性能數據用於衡量應用程序。換句話說,應用程序需要通過創建性能計數器對象來提供數據。

 

應用程序性能測量的類型

幾乎所有的應用程序的性能測量屬於以下六大類。

瞬時值:- 很多時候,我們只是要測量當前值。例如,我們希望衡量有多少客戶記錄已被處理,有多少RAM內存已被使用等,這些指標被稱為瞬時值或者絕對值。性能計數器通過瞬時計數器支持這些類型的測量。

平均值:- 有時瞬間/當前值並不展現真實的情況。例如,只是說應用程序消耗1GB的空間是不夠的。但是,如果我們能夠得到某種內存消耗的平均數據,如1000個記錄消耗的空間是10MB,也許你可以更深入了解應用程序里面發生了什么。性能計數器通過使用像AverageBase,AverageTimer32,AverageCount64等類型支持這些種類型的測量。

速率值:- 有些情況下,當你想知道事件相對於時間的比率。例如,你想知道每秒有多少條記錄被處理。速率計數器幫助我們計算這些性能指標。

百分比值:- 很多時候,我們想看到以百分比值來作比較。比如你要比較兩台計算機之間的性能數據。比較直接的值將不會是一個公平的比較。因此,如果我們能有兩台計算機的%值,比較會更有意義。如果我們要比較不同性能計數器的值,百分比是更好的選擇,而不是絕對值。

例如,如果你想把RAM使用情況和硬盤空間使用情況做比較。把50GB硬盤使用情況和1GB RAM的使用情況做比較,就如同比較蘋果與橘子。如果你使用百分比來表達,這樣的比較更公平和合理。百分比性能計數器可以幫助我們以百分比來表達絕對值。

差異值:- 很多時候,我們希望得到差值的性能數據,比如從應用程序開始有多少時間流逝,從應用程序開始有多少硬盤消耗。為了收集這些類型的性能數據,我們需要記錄原始值和最新值。為了得到最終的性能數據,我們需要從當前值減去原始值。性能計數器提供差值計數器計算這樣的性能數據。

總之,有5種類型的性能計數器,可滿足上述所有計數需求。正如下圖所表現的:

clip_image005

 

將用於被性能計數器測試的示例程序

在整篇文章中,我們將用接下來要說明的一個簡單的程序作為計數器的例子。在這個例子中,我們將有一個定時器,每隔100毫秒產生一個隨機數。這些隨機數將被檢查看它是否小於2。如果是,那么函數‘MyFunction’將被調用。

clip_image006

 

下面的代碼中,計時器將每100毫秒運行一次並產生隨機數,如果隨機數小於2則調用‘MyFunction’函數。

private void timer1_Tick(object sender, EventArgs e)
{
// Generate random number between 1 to 5.
Random objRnd = new Random();
int y = objRnd.Next(1, 5);

// If random number is less than 2 call my Function
if (y > 2)
{
MyFunction();
}
}

 

下面是'MyFunction'函數的代碼,它是當隨機數的值小於2時被調用的。該方法不會做任何事情。

private void MyFunction()
{

}

 

本文中我們所有的性能計數器的例子,將使用上述定義的代碼示例。

 

 

 

加入我們的第一個瞬時性能計數器的4個步驟

在我們深入‘如何增加一個性能計數器’這個問題之前,讓我們先來了解一下性能計數器的結構。當我們創建性能計數器,它需要被加入某些類別。因此,我們需要創建一個類別,並且把所有性能計數器放在該類別下。

clip_image008

 

我們來計數‘MyFunction’ 被調用了多少次。首先讓我們來創建一個名為“NumberOfTimeFunctionCalled”的即時計數器。在此之前,讓我們來看看有多少不同類型的瞬時計數器被性能計數器所支持: -

一下定義摘自:http://msdn.microsoft.com/en-us/library/system.diagnostics.performancecountertype.aspx

NumberOfItems32- 即時計數器,它顯示最近觀測到的值。

NumberOfItems64- 即時計數器,它顯示最近觀測到的值。 例如,用於維護大量的項或操作的簡單計數。 它與 NumberOfItems32 相同,但它使用更大的字段來容納較大的值。

NumberOfItemsHEX32- 即時計數器,它以十六進制形式顯示最近觀測到的值。 例如,用於維護項或操作的簡單計數。

NumberOfItemsHEX64- 即時計數器,它顯示最近觀測到的值。 例如,用於維護大量的項或操作的簡單計數。 它與 NumberOfItemsHEX32相同,但它使用更大的字段來容納較大的值。

 

1步 創建計數器:- 對於我們的當前的場景,‘NumberOfItems32’足夠了。所以,我們首先創建'NumberOfItems32‘即時計數器。有兩種方式,一種是通過代碼,另一種是使用VS 2008的server explorer來創建計數器。代碼的方法,我們將在后面看到。現在我們先使用server explorer來創建我們的計數器。因此,打開您的Visual Studio,點擊View,打開Server explorer,你會看到下面的圖中所示的“Performance Counters”節點。右鍵單擊“Performance Counters”節點,選擇“create new category”。

clip_image009

 

當我們創建了一個新的類別,您可以指定的類別名稱,並在類別中添加計數器。對於當前的例子,我們給定類別的名稱為“MyApplication”,並且添加類型為'NumberOfItem32',名稱為'NumberOfTimeFunctionCalled”的計數器。

clip_image010

 

 

2步 在你的Visual Studio應用程序中添加計數器:- 一旦你已經把計數器添加到server explorer上,你可以把計數器控件拖放到ASPX頁面上,如下圖所示。

你需要把只讀”屬性標記為false,這樣你可以從代碼中修改計數器的值。

clip_image011

 

 

3步 添加為計數器計數的代碼:- 最后,我們需要遞增計數器的值。窗體加載過程中,我們首先清除所有計數器的舊值。請注意,計數器的值是作為全局值保存的,所以他們不會自己重置,需要我們顯式地重置。因此,在窗體加載時把原始值設置為零。

private void Form1_Load(object sender, EventArgs e)
{
perfNumberOfTimeFunctionCalled.RawValue = 0;
}

 

當函數被調用時,我們通過使用‘Increment’方法來遞增計數器的值。每次increment函數的調用,值增加1。

 

private void MyFunction()
{
perfNumberOfTimeFunctionCalled.Increment();
}

 

第4步 查看計數器數據:- 現在,我們已經指定了計數器在每次‘MyFunction’函數被調用時,遞增其值。現在我們使用性能監視器(performance monitor)來顯示性能計數器。打開‘Run’並輸入‘perfmon’。你會看到有很多默認的性能計數器,清晰起見,我們現在刪除所有的計數器,加入我們的性能計數器即‘NumberofTimeFunctionCalled‘。

clip_image012

 

現在,您可以看到如下圖所示的圖表。請確保您的應用程序正在運行,因為需要由應用程序發出數據,然后展現在performance monitor上。

clip_image013

 

上述視圖是圖表視圖,要查看相同數據的文本格式,你可以使用性能監視器提供的‘view report’選項卡。你可以看到該報告顯示,從程序開始運行,‘MyFunction的’被調用了9696次。

clip_image014

 

創建更合理的計數器

在前面的章節中,我們測量了‘MyFunction’被調用的次數。但這樣的性能計數並沒有真正顯示任何的測量價值。最好是,我們也能看到計時器被調用次數,然后我們就能夠把計時器被調用的次數和‘MyFunction’被調用的次數做比較。

因此,我們創建一個即時計數器,當定時器觸發時遞增該計數器。如下面的代碼所示。

private void timer1_Tick(object sender, EventArgs e)
{
perfNumberOfTimeTimerCalled.Increment();
Random objRnd = new Random();
int y = objRnd.Next(1, 5);
if (y > 2)
{
MyFunction();
}
}

 

你可以在下面的圖表中可以看到這兩個計數器,藍色的線表示‘MyFunction’被調用的次數,黑色的線表示timer被調用的次數。

clip_image015

 

如果我們看一下‘report view’,我們也可以看到timer被觸發多少次,‘MyFunction’被調用多少次。

clip_image016

 

平均性能計數器

在前面的章節中,我們用到了2個性能計數器,一個告訴我們timer被觸發了多少次,另一個告訴我們‘MyFunction’被調用了多少次。如果我們能有某種平均數據,告訴我們timer每調用一次‘MyFunctionCalled’計數多少次,它將更有意義。

 

為了得到這些類型的指標,需要用到平均性能計數器。因此,對於我們的場景,我們需要計數函數的調用次數和timer的觸發次數。然后,我們需要將他們相除,得到timer每觸發一次函數調用多少次。

clip_image017

 

我們需要添加兩個計數器,一個作為分子另一個作為分母。對於作為分子的計數器,我們需要添加‘AverageCount64’類型的計數器,同時為分母,我們需要添加‘AverageBase’類型的計數器。

clip_image018

 

在‘AverageCount64’類型計數器之后,你需要添加‘AverageBase‘計數器,否則,你會得到一個錯誤,如下圖所示。

clip_image019

 

我們對於每一個timer觸發,我們都對用於記錄timer調用的計數器進行遞增。

private void timer1_Tick(object sender, EventArgs e)
{
perfAvgNumberofTimeTimerCalled.Increment();
Random objRnd = new Random();
int y = objRnd.Next(1, 5);
if (y > 2)
{
MyFunction();
}
}

 

為每一次函數調用我們都對用於記錄函數調用次數的計數器進行遞增

private void MyFunction()
{

perfNumberOfTimeFunctionCalled.Increment();

}

 

如果你運行該程序,在view report模式下你應該會看到如下圖所示。你可以看到平均‘MyFunction’被調用約0.5次(每timer觸發一次)。

clip_image020

 

如果你自己做計算,你將得到和性能監視器相同的計算值。

clip_image021

 

 

速率性能計數器

在我們的示例中,我們現在想找出‘MyFunction’相對於時間的比率。我們想知道每秒鍾被調用了多少次。因此,瀏覽server explorer,並添加‘rateofCountsPerSecond32’計數器如下面的圖所示。當‘MyFunction’每次被調用,遞增此計數器。

clip_image022

 

如果您運行的應用程序,你將能夠看到“RateofMyFunctionCalledPerSecond”的值。下面是一個簡單的報告,該報告顯示運行15秒后計數器的速率數據。在這15秒中總調用次數為72次。因此,平均每秒調用5次‘MyFunction’。

clip_image023

 

 

剩下的性能計數器

我們還剩下百分比計數器和差異計數器,因為他們是非常簡單和直接的,為了保持本文的焦點和特性,我在文中不再介紹這兩種計數器


通過C#代碼添加計數器

到現在我們已經通過server explorer來增加性能計數器。你還可以通過代碼來添加計數器。第一件事就是,我們需要導入System.Diagnostics命名空間。

然后,我們需要創建‘CounterCreationDataCollection’ 對象。

CounterCreationDataCollection Mycounters = new CounterCreationDataCollection();

 

創建實際的計數器並指定計數器的類型。

CounterCreationData totalOps = new CounterCreationData();
totalOps.CounterName = "Numberofoperations";
totalOps.CounterHelp = "Total number of operations executed";
totalOps.CounterType = PerformanceCounterType.NumberOfItems32;
Mycounters.Add(totalOps);

 

最后,在類別中創建計數器。下面的代碼片斷用於在‘MyCategory’類別中創建計數器。

PerformanceCounterCategory.Create("MyCategory","Sample category for Codeproject", Mycounters);

 

讓我們用Performance counter helper來緩解我們的痛苦

寫性能計數器創建代碼是很痛苦的。使用performance counter helper可以幫助你緩解這種痛苦並使你的代碼更小巧。你可以一下網站找到performance counter helper:http://perfmoncounterhelper.codeplex.com/

 

不要在產品中使用

是的,只在開發時使用性能計數器。如果您在產品中使用,確保有一個啟用和禁用機制,否則會影響應用程序的性能。

 

總結

使用性能計數器測量應用程序的數據。
性能計數器包含多種類型,如瞬時,平均,速率等。

性能計數器不應該在產品中用到。如果用到了,確保有一個禁用機制。
性能計數器自身並不能進行測量,它需要應用程序提供數據,這樣性能監視器才可以計算並顯示的數據。


源代碼

這里你可以找到並下載上述性能計數器討論的示例源代碼。

 

其他最佳實踐

最佳實踐第1部分,請單擊此處

最佳實踐第2部分,請單擊此處

最佳實踐第4部分,請單擊此處

最佳實踐第5部分,請單擊此處

 

我的FAQ文章

(譯者:廣告時間)

我明白這不是談論我FAQ文章正確的地方。只是想稱贊一下自己花費一年時間來完成的FAQ系列。下面是全部的鏈接:

Silverlight FAQ :- http://www.codeproject.com/KB/WPF/WPFSilverLight.aspx
LINQ FAQ :- http://www.codeproject.com/KB/linq/LINQNewbie.aspx
WWF FAQ :- http://www.codeproject.com/KB/WF/WWF.aspx
WCF FAQ :- WCF.aspx
Sharepoint FAQ :- SharePoint.aspx
Ajax FAQ :- AjaxQuickFAQ.aspx
Architecture FAQ :- SoftArchInter1.aspx
Localization and globalization :- LocalizationGlobalizPart1.aspx
Project management FAQ :- ProjectManagementFAQ.aspx

 

關於作者

Shivprasad koirala

clip_image024

構架師http://www.questpond.com
clip_image025印度

我是微軟ASP / ASP.NET MVP,目前
印度的一家小的E-learning公司的CEO 。我們非常積極地編寫培訓視頻,寫書和企業培訓。訪問我的網站

.NET, C# , design pattern , WCF , Silverlight
, LINQ , ASP.NET , ADO.NET , Sharepoint , UML , SQL Server  training 
and Interview questions and answers



 

本文由知平軟件劉斌華翻譯,轉載請注明出處。原文地址:http://www.codeproject.com/Articles/42001/NET-Best-Practice-No-3-Using-performance-counters

最佳實踐1和2已經有其他網友翻譯,一下給出鏈接:http://www.cnblogs.com/mickeychang/archive/2009/09/17/1568670.html

http://www.cnblogs.com/mickeychang/archive/2009/08/29/1556527.html

 

本人暫時沒有翻譯最佳實踐4和5的計划。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM