2010-10-09 67 views
9

使性能計數器啓動並運行的最小C#代碼量是多少?最簡單的可能性能計數器示例

我只是想測量我的代碼中兩個點之間的CPU週期數和/或時間。我已經瀏覽了網頁上的所有華夫餅,但它看起來像WAY更多的代碼比這樣一個瑣碎的任務所需的代碼。我只想快速測量並運行,並將更多精力放在我正在進行的工作上。

回答

26

我不認爲你需要一個性能計數器。你是否需要超過從StopWatch得到的時間?這是非常準確的。

Stopwatch watch = Stopwatch.StartNew(); 

// Do work 

watch.Stop(); 
// elapsed time is in watch.Elapsed 

但是,要回答您實際詢問的問題:如果您只是想查詢現有的計數器,它實際上很簡單。這裏是一個完整的例子:

using System; 
using System.Diagnostics; 
using System.Linq; 

static class Test 
{ 
    static void Main() 
    { 
     var processorCategory = PerformanceCounterCategory.GetCategories() 
      .FirstOrDefault(cat => cat.CategoryName == "Processor"); 
     var countersInCategory = processorCategory.GetCounters("_Total"); 

     DisplayCounter(countersInCategory.First(cnt => cnt.CounterName == "% Processor Time")); 
    } 

    private static void DisplayCounter(PerformanceCounter performanceCounter) 
    { 
     while (!Console.KeyAvailable) 
     { 
      Console.WriteLine("{0}\t{1} = {2}", 
       performanceCounter.CategoryName, performanceCounter.CounterName, performanceCounter.NextValue()); 
      System.Threading.Thread.Sleep(1000); 
     } 
    } 
} 

當然,該過程將需要適當的權限來訪問您需要的性能計數器。

+0

也許我應該闡述一下,我試圖實現一個簡單的正則表達式引擎。秒錶會精確到足夠嗎? – 2010-10-09 09:21:39

+0

@保羅馬修斯 - 它會好的。秒錶分辨率爲 – Oded 2010-10-09 09:24:44

+1

如果您正在詢問您的代碼,那麼測量代碼的性能就足夠準確。如果要測量性能,請記住在Visual Studio之外的版本模式下運行代碼。另外,我建議您使用分析器來衡量性能,它會告訴您更多關於代碼性能的信息,而不僅僅是簡單的點對點時間測量。 – driis 2010-10-09 09:27:18

2

有沒有微不足道的方式來得到這個啓動和運行在.NET中。但是,我發現的最簡單的方法是在企業庫的基礎上構建,它提供了一些開箱即用的性能計數器功能。例如:the Performance Counter Handler

企業庫還爲您提供了一些功能,可以更輕鬆地管理性能計數器的安裝。

此外,它讓你建立在它之上的話,你可以創建一個AvergeTimeMeter它允許你只是這樣做:

private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounter = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTime); 
private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounterBase = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTimeBase); 

public void DoSomethingWeWantToMonitor() 
{ 
    using (new AverageTimeMeter(averageRequestTimeCounter, averageRequestTimeCounterBase)) 
    { 
     // code here that you want to perf mon 
    } 
} 

這可以讓你簡單地封裝代碼要在監視使用塊 - 並專注於您實際需要處理的代碼,而不必擔心所有性能計數器基礎結構。

要做到這一點,你需要創建一個可重用的AverageTimeMeter類是這樣的:

public sealed class AverageTimeMeter : IDisposable 
{ 
    private EnterpriseLibraryPerformanceCounter averageCounter; 
    private EnterpriseLibraryPerformanceCounter baseCounter; 
    private Stopwatch stopWatch; 
    private string instanceName; 

    public AverageTimeMeter(EnterpriseLibraryPerformanceCounter averageCounter, EnterpriseLibraryPerformanceCounter baseCounter, string instanceName = null) 
    { 
     this.stopWatch = new Stopwatch(); 
     this.averageCounter = averageCounter; 
     this.baseCounter = baseCounter; 
     this.instanceName = instanceName; 
     this.stopWatch.Start(); 
    } 

    public void Dispose() 
    { 
     this.stopWatch.Stop(); 
     if (this.baseCounter != null) 
     { 
      this.baseCounter.Increment(); 
     } 

     if (this.averageCounter != null) 
     { 
      if (string.IsNullOrEmpty(this.instanceName)) 
      { 
       this.averageCounter.IncrementBy(this.stopWatch.ElapsedTicks); 
      } 
      else 
      { 
       this.averageCounter.SetValueFor(this.instanceName, this.averageCounter.Value + this.stopWatch.ElapsedTicks); 
      } 
     } 
    } 

} 

你必須註冊您的性能計數器(在EntLib例所示),但是這應該讓你開始。

+0

根據我現在看到的評論,看起來或許你的問題更多地涉及到測量代碼,而不是特別針對性能計數器。我總是從性能計數器的角度來看這個問題 - 如果你不需要這個,我同意Stopwatch是最簡單的方法。 – 2010-10-09 09:29:10

+0

我最後一次使用性能計數器是在Delphi中,所以也許術語有所改變。對不起,如果我帶領你走上花園的道路:) – 2010-10-09 09:38:11

-1

您可以使稱爲計數器的靜態變量長,並使一個線程增加它。您可以隨時啓動並中止該線程,只要您需要和/或需要。在線程運行時,可以使用靜態計數器的整數值來測量代碼中CPU週期數和/或兩點之間的時間。線程和靜態計數器技術可以與Stopwatch Start Stop重新啓動重置方法和ElapsedTicks屬性的使用進行比較。

+1

聽起來像一個有趣的方法。我真的不明白如何使用另一個線程來衡量CPU週期會給我們一個準確的測量?我們是否確保該線程佔用與我們測量的線程完全相同的CPU時間片? – 2013-10-06 21:39:41

6

我喜歡的東西,可以採取任何代碼塊,並用秒錶剖析代碼包裝它來測量時間花在執行它:

using System.Diagnostics; 
    using System.Threading; 

    public static T Profile<T>(Func<T> codeBlock, string description = "") 
    { 
     Stopwatch stopWatch = new Stopwatch(); 
     stopWatch.Start(); 
     T res = codeBlock(); 
     stopWatch.Stop(); 
     TimeSpan ts = stopWatch.Elapsed; 
     const double thresholdSec = 2; 
     double elapsed = ts.TotalSeconds; 
     if(elapsed > thresholdSec) 
      System.Diagnostics.Debug.Write(description + " code was too slow! It took " + 
      elapsed + " second(s)."); 
     return res; 
    } 

然後調用它像:

Profile(() => MyObj.MySlowMethod()); 

或:

Profile(() => MyObj.MySlowMethod(), "I can explain why"); 
+0

確實非常酷! – 2015-03-10 02:01:15