Beispiel für eigene PerformanceCounter  
Frank Dzaebel, erstellt am: 17.12.06, zuletzt geändert:  17.12.06
Kategorie: Implementation, .NET-Version: 2.0, [Download]

Leistungsindikatoren (PerformanceCounter) sind eine geeignete Art um Messungen vielerlei Art anderen Anwendungen zugänglich zu machen. Windows selber bietet über das Tool Perfmon eine anpassbare flexible Monitoring-Anwendung, mit der nicht nur vordefinierte, sondern auch eigene Leistungsindikatoren darstellbar sind.

 
 

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Windows.Forms;

// [PerformanceCounter-Klasse]

public class PerfTest
{
  private static PerformanceCounter pc;
  private static PerformanceCounter bpc;
  private static TextBox ausgabeTextBox;

  public static void Start(TextBox ausgabeTextBox)
  {
    PerfTest.ausgabeTextBox = ausgabeTextBox;
    List<CounterSample> samplesList = new List<CounterSample>();
    KategorieErzeugen(); CounterErzeugen();
    CounterSamplesErstellenUndAusgeben(samplesList);
    ErgebnisseAusgeben(samplesList);
  }

  private static bool KategorieErzeugen()
  {
    if (!PerformanceCounterCategory.Exists("MeineKategorie"))
    {
      CounterCreationDataCollection ccdc = new CounterCreationDataCollection();

      // Hinzufügen des Counters.
      CounterCreationData averageCount64 = new CounterCreationData();
      averageCount64.CounterType = PerformanceCounterType.AverageCount64;
      averageCount64.CounterName = "MeinCounterBeispiel";
      ccdc.Add(averageCount64);

      // Hinzufügen des BaseCounters.
      CounterCreationData averageCount64Base = new CounterCreationData();
      averageCount64Base.CounterType = PerformanceCounterType.AverageBase;
      averageCount64Base.CounterName = "MeinCounterBeispielBase";
      ccdc.Add(averageCount64Base);

      // Erzeugen der Kategorie.
      PerformanceCounterCategory.Create("MeineKategorie",
        "Demonstriert den Gebrauch von AverageCount64 PerformanceCounter-Typen.",
        PerformanceCounterCategoryType.SingleInstance, ccdc);

      return (true);
    }
    else
    {
      Ausgabe("Kategorie existiert - MeineKategorie");
      return (false);
    }
  }

  private static void CounterErzeugen()
  {
    // Erzeugen des Counters.
    pc = new PerformanceCounter("MeineKategorie", "MeinCounterBeispiel", false);
    bpc = new PerformanceCounter("MeineKategorie","MeinCounterBeispielBase", false);
    pc.RawValue = 0; bpc.RawValue = 0;
  }

  /// <summary>CounterSamples werden erstellt und ausgegeben</summary>
  private static void CounterSamplesErstellenUndAusgeben(List<CounterSample> samplesList)
  {
    Random r = new Random(DateTime.Now.Millisecond);

    // Durch die CounterSample's iterieren.
    for (int j = 0; j < 100; j++)
    {
      int value = r.Next(1,10);
      AusgabeNoCR(j + " = " + value);

      pc.IncrementBy(value);
      bpc.Increment();

      if ((j % 10) == 9)
      {
        AusgabeCounterSample(pc.NextSample());
        samplesList.Add(pc.NextSample());
      }
      else
        Ausgabe("");

      System.Threading.Thread.Sleep(50);
    }
  }

  // Die für diese Umgebung definierte Zeichenfolge für einen Zeilenumbruch.
  static string NL = Environment.NewLine;

  /// <summary>Gibt die Meldungen in die bei Start() definierte TextBox mit CarriageReturnLineFeed aus.</summary>
  private static void Ausgabe(string p)
  {
    ausgabeTextBox.AppendText(p+NL);
  }

  /// <summary>Gibt die Meldungen in die bei Start() definierte TextBox ohne CarriageReturnLineFeed aus.</summary>
  private static void AusgabeNoCR(string p)
  {
    ausgabeTextBox.AppendText(p);
  }
  
  /// <summary>Ausgabe aller CounterSamples</summary>
  private static void ErgebnisseAusgeben(List<CounterSample> samplesList)
  {
    for (int i = 0; i < (samplesList.Count - 1); i++)
    {
      // Ausgabe des CounterSamples.
      AusgabeCounterSample((CounterSample)samplesList[i]);
      AusgabeCounterSample((CounterSample)samplesList[i + 1]);

      // Nutzung von .NET um den CounterValue zu berechnen.
      Ausgabe("Von .NET berechneter CounterValue = " +
        CounterSampleCalculator.ComputeCounterValue((CounterSample)samplesList[i],
        (CounterSample)samplesList[i + 1]));

      // Manuelle Berechnung des Counters.
      Ausgabe("Mein berechneter CounterValue = " +
        MeineCounterValueBerechnung((CounterSample)samplesList[i],
        (CounterSample)samplesList[i + 1]));
    }
  }

  /// <summary>
  /// ==================================================================================
  /// Beschreibung: Dieser Counter-Typ zeigt, wieviele Messwerte durchschnittlich 
  ///    während eines Vorgangs verarbeitet werden. Counter dieses Typs zeigen
  ///    ein Verhältnis der verarbeiteten zu den abgeschlossenen Vorgänge auf.
  ///    Dieses Verhältnis wird immer bzgl. des letzten Intervalls berechnet.
  /// Generischer Typ: Durchschnitt
  ///    Formel: (N1 - N0) / (D1 - D0), wobei N die Anzahl der *verarbeiteten* 
  ///    Mess-Vorgänge und D die Anzahl der *abgeschlossenen* Mess-Vorgänge bzgl. des
  ///    letzten Intervalls repräsentiert.
  ///  Durchschnitt: (Nx - N0) / (Dx - D0)  
  ///  Beispiel: PhysicalDisk\Avg. Disk Bytes / Transfer 
  /// =================================================================================
  ///</summary>
  private static Single MeineCounterValueBerechnung(CounterSample s0,CounterSample s1)
  {
    Single numerator = (Single)s1.RawValue - (Single)s0.RawValue;
    Single denomenator = (Single)s1.BaseValue - (Single)s0.BaseValue;
    Single counterValue = numerator / denomenator;
    return (counterValue);
  }

  /// <summary>Ausgabe der Informationen über das CounterSample (eine Struktur,
  /// die die unformatierten Daten für einen Leistungsindikator enthält)</summary>
  private static void AusgabeCounterSample(CounterSample s)
  {
    Ausgabe(NL+"====================");
    Ausgabe("CounterSample-Werte:");
    Ausgabe("   BaseValue        = " + s.BaseValue);
    Ausgabe("   CounterFrequency = " + s.CounterFrequency);
    Ausgabe("   CounterTimeStamp = " + s.CounterTimeStamp);
    Ausgabe("   CounterType      = " + s.CounterType);
    Ausgabe("   RawValue         = " + s.RawValue);
    Ausgabe("   SystemFrequency  = " + s.SystemFrequency);
    Ausgabe("   TimeStamp        = " + s.TimeStamp);
    Ausgabe("   TimeStamp100nSec = " + s.TimeStamp100nSec);
    Ausgabe("==================="+NL);
  }
}