web-dev-qa-db-ja.com

最も単純なパフォーマンスカウンターの例

パフォーマンスカウンターを稼働させるためのC#コードの最小量はどれくらいですか?

コード内の2つのポイント間のCPUサイクル数や時間を測定したいだけです。私はウェブ上のすべてのワッフルをざっと読みましたが、そのような些細な作業に必要なコードよりもはるかに多くのコードのようです。迅速な測定を開始して実行し、自分が取り組んでいることにもっと集中したいだけです。

14
Paul Matthews

そのためのパフォーマンスカウンターは必要ないと思います。 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);
        }
    }
}

もちろん、プロセスには、必要なパフォーマンスカウンターにアクセスするための適切な権限が必要です。

30
driis

私は、任意のコードブロックを取得し、それをストップウォッチプロファイリングコードでラップして、実行に費やされた時間を測定できるものが好きです。

    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");
9
yǝsʞǝla

これを.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の例に示されている)を登録する必要がありますが、これで開始できます。

2