パフォーマンスカウンターを稼働させるためのC#コードの最小量はどれくらいですか?
コード内の2つのポイント間のCPUサイクル数や時間を測定したいだけです。私はウェブ上のすべてのワッフルをざっと読みましたが、そのような些細な作業に必要なコードよりもはるかに多くのコードのようです。迅速な測定を開始して実行し、自分が取り組んでいることにもっと集中したいだけです。
そのためのパフォーマンスカウンターは必要ないと思います。 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);
}
}
}
もちろん、プロセスには、必要なパフォーマンスカウンターにアクセスするための適切な権限が必要です。
私は、任意のコードブロックを取得し、それをストップウォッチプロファイリングコードでラップして、実行に費やされた時間を測定できるものが好きです。
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");
これを.NETで起動して実行するための簡単な方法はありません。ただし、私が見つけた最も簡単な方法は、パフォーマンスカウンターを操作するためのすぐに使用できる機能を提供するエンタープライズライブラリの上に構築することです。例: パフォーマンスカウンターハンドラー
エンタープライズライブラリには、パフォーマンスカウンターのインストールをはるかに簡単に管理するためのいくつかの機能もあります。
さらに、その上に構築できるので、次のことを実行できる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
}
}
これにより、監視するコードをusingブロックにカプセル化するだけで、すべてのパフォーマンスカウンターインフラストラクチャについて心配することなく、実際に作業するコードに集中できます。
これを行うには、次のような再利用可能な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の例に示されている)を登録する必要がありますが、これで開始できます。