Performance Counters in C#

  1. Inleiding
  2. Performance Monitor / perfmon
  3. Performance Counters
  4. Een bestaande Performance Counter gebruiken
  5. Een eigen Performance Counter creëren
  6. Slot
  7. Voorbeeldprogramma

Inleiding

Je programma is niet vooruit te branden, maar is dat de schuld van jouw programma of is de desbetreffende computer of het netwerk waarop je programma draait het dode paard? Iedereen gaat er vanzelfsprekend vanuit dat jouw programma de bron is van al het kwaad, maar met de Performance counters (prestatiemeters) kunnen we zien waar het dode paard echt ligt.

up | down

Performance Monitor / perfmon

De prestatiemeters kunnen bekeken worden met de Performance Monitor. De Performance Monitor is een hulpprogramma van Windows en op te starten met de Run functie (te vinden onder de Windows start button) waarna je het commando perfmon ingeeft:

up | down

Performance Counters

De Performance monitor kent een aantal Performance Counters (prestatiemeters) en met die counters meet je verschillende dingen zoals netwerkgebeurtenissen of gebeurtenissen m.b.t. het geheugen. Je wilt m.b.t het netwerk bijvoorbeeld weten hoeveel bytes per seconde worden overgebracht of je wilt m.b.t het geheugen weten hoeveel Mb nog beschikbaar is.

Voor systeembeheerders zeer interessant, maar ook voor programmeurs en software developers kunnen Performance Counters interessant zijn. Performance Counters kunnen namelijk gebruikt worden om te kunnen bepalen hoe het systeem er aan toe is. Hoe “fit” is het systeem en heeft het met de huidige gesteldheid van het systeem sowieso nog zin om je programma erop te laten draaien?

En ook niet onbelangrijk, wat is de performance van je programma en hoe gedraagt het systeem zich als je programma draait? Ook daarvoor kunnen Performance Counters gebruikt worden.

up | down

Een bestaande Performance Counter gebruiken

Het onderstaande scherm krijg je te zien nadat je de Performance Monitor (commando perfmon) hebt opgestart. Klik op de “+” om de Performance Counter categorieën te zien.

Selecteer vervolgens Performance Counter category Memory. Performance Counter Available MBytes is één van de prestatiemeters die vallen onder de Memory Performance Counter category:

Click to enlarge…

En we kunnen performance counter Available MBytes als volgt uitlezen:

PerformanceCounter performanceCounter =
new PerformanceCounter(categoryName:"Memory",
                       counterName :"Available MBytes",
                       readOnly    : true);

Console.WriteLine(
   "Beschikbaar geheugen: {0}",
   performanceCounter.NextValue()); 

Waarbij we een resultaat zoals onderstaand kunnen krijgen. De prestatiemeter kunnen we uitlezen vanuit code, maar we kunnen ook de Performance Monitor ervoor gebruiken. De Performance Monitor toont real time in een grafiek de waarden van de prestatiemeter en ook hoe de waarden veranderen in de loop der tijd.

De desbetreffende Performance Counter is interessant om te gebruiken als we bijvoorbeeld weten dat ons programma een minimale hoeveelheid geheugen nodig heeft. We kunnen dan programmeren dat het programma niet verder gaat als uit de Performance Counter blijkt dat op de computer niet genoeg geheugen beschikbaar is.

up | down

Een eigen Performance Counter creëren

Je kunt ook je eigen prestatiemeters creëren. We maken Performance Counter Teller en een TestCategorie Performance Counter Category. Het hoofdprogramma:

static void Main(string[] args)
{
  try
  {
    // de prestatiemeter
    string categorie = "TestCategorie";
    string teller = "Teller";

    // eerst verwijderen
    VerwijderPerformanceCounters(categorie);

    // creëren
    MaakPerformanceCounters(categorie, teller);
    
    // vullen
    VulPerformanceCounters(categorie, teller);
    
    // uitlezen
    LeesPerformanceCounters(categorie, teller);
    
    // gezien?
    Console.WriteLine("Gezien?");
  }
             
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);
  }
  
  finally
  {
    Console.ReadKey();
  }
}

We gaan eerst kijken of de prestatiemeter al bestaat. We verwijderen de prestatiemeter als de prestatiemeter al mocht bestaan.

static void VerwijderPerformanceCounters(
            string categorie)
{
  if (PerformanceCounterCategory.Exists(categorie))
  {
    Console.WriteLine(
    "Verwijder PerformanceCounterCategory {0}", 
    categorie);
    PerformanceCounterCategory.Delete(categorie);
  }
}

Nu de code om de prestatiemeter te creëren. Prestatiemeter teller kan numerieke waarden bevatten omdat we hebben aangegeven dat de prestatiemeter van het type NumberOfItems32 is.

static void MaakPerformanceCounters(
       string categorie, string teller)
{
  Console.WriteLine(
  "Maak PerformanceCounter Category {0} Counter {1} ", 
        categorie, teller);
  if (!PerformanceCounterCategory.Exists(categorie))
  {
             
    //Definieer de PerformanceCounter(s)
    CounterCreationData performanceCounter =
    new CounterCreationData(
    counterName: teller,
    counterHelp: "Om een telling te doen",
    counterType: PerformanceCounterType.NumberOfItems32);
                    
    //Definieer een Collectie
    CounterCreationDataCollection 
    performanceCounterCollectie = 
    new CounterCreationDataCollection();
                
    //Voeg de PerformanceCounter(s) toe aan de collectie
    performanceCounterCollectie.Add(performanceCounter);
                
    //Definieer de PerformanceCounter Category
    PerformanceCounterCategory.Create(
       categoryName: categorie,
       categoryHelp: "Een Test PerformanceCounter Categorie",
       categoryType: PerformanceCounterCategoryType.SingleInstance,
       counterData : performanceCounterCollectie);
                
    Console.WriteLine(
    "PerformanceCounter 
     Category {0} met Counter {1} is gecreëerd.", 
     categorie, teller);
  }
}

We hebben de prestatiemeter gecreëerd en in onderstaand stukje code gaan we de prestatiemeter gebruiken. We gebruiken een for {} lus waarin we vijf keer iets herhalen. De prestatiemeter wordt aan het einde van elke herhaling opgehoogd met de waarde 10 en er wordt een seconde gewacht voordat met de volgende herhaling wordt begonnen.

static void VulPerformanceCounters(string categorie, string teller)
{
  Console.WriteLine(
  "VulPerformanceCounter 
  Category {0} met Counter {1}.", 
  categorie, 
  teller);
  if (PerformanceCounterCategory.Exists(categorie))
  {
     PerformanceCounter performanceCounter = 
     new PerformanceCounter(categoryName:categorie, 
                            counterName :teller, 
                            readOnly    :false);
     // reset
     performanceCounter.RawValue = 0;
     for (int i = 1; i < 6; i++)
     {
        Console.WriteLine("Actie {0}", i);
        performanceCounter.IncrementBy(10);
        Thread.Sleep(1000);
     }
  }
}

We starten het programma:

Click to enlarge…

En we zien in de  Performance Monitor hoe prestatiemeter Teller in een tijdsbestek van vijf seconden wordt opgehoogd van de waarde 0 naar 50:

Click to enlarge…

up | down

Slot

Ik heb laten zien hoe je een bestaande prestatiemeter kunt gebruiken en hoe je een eigen prestatiemeter kunt creëren. De Performance Counters in de voorbeelden zijn vrij eenvoudig, maar je kunt voor het serieuzere meetwerk uiteraard meer geavanceerde PerformanceCounters maken of gebruiken.

Met Performance Counters (prestatiemeters) heb je in ieder geval iets concreets wat je bijvoorbeeld bij performance issues kan gebruiken. Wat is de oorzaak van het probleem? Zakt de performance van het netwerk als een plumpudding in elkaar zodra jouw programma wordt opgestart? Of was de performance van het netwerk, los van het wel of niet opgestart wezen van je programma, al drie keer niets? Een prestatiemeter kan antwoord geven op die vragen. Misschien dat de performance issue uiteindelijk wordt veroorzaakt door een kapotte hardware component en dat het niet aan het programma in kwestie ligt?

Hopelijk ben je met deze posting weer wat wijzer geworden en ik hoop je weer terug te zien in één van mijn volgende blog posts. Wil je weten wat ik nog meer over C# heb geschreven? Hit the C# button…

up | down


Voorbeeldprogramma

using System;
using System.Diagnostics;
using System.Threading;

namespace PerformanceCounter2
{
 class Program
 {
   // Main
   static void Main(string[] args)
   {
     try
     {
       // de prestatiemeter
       string categorie = "TestCategorie";
       string teller = "Teller";
        
       // eerst verwijderen
       VerwijderPerformanceCounters(categorie);
            
       // creëren
       MaakPerformanceCounters(categorie, teller);
       
       // vullen
       VulPerformanceCounters(categorie, teller);
       
       // uitlezen
       LeesPerformanceCounters(categorie, teller);
       
       // gezien?
       Console.WriteLine("Gezien?");
     }
              
     catch (Exception ex)
     {
       Console.WriteLine(ex.Message);
     }
      
     finally
     {
       Console.ReadKey();
     }
   }
   
   // VerwijderPerformanceCounters
   static void VerwijderPerformanceCounters(
               string categorie)
   {
     if (PerformanceCounterCategory.Exists(categorie))
     {
       Console.WriteLine(
       "Verwijder PerformanceCounterCategory {0}", 
       categorie);
       PerformanceCounterCategory.Delete(categorie);
     }
   }
   
   // MaakPerformanceCounters
   static void MaakPerformanceCounters(
          string categorie, string teller)
   {
     Console.WriteLine(
     "Maak PerformanceCounter Category {0} Counter {1} ", 
           categorie, teller);
     if (!PerformanceCounterCategory.Exists(categorie))
     {
                  
       //Definieer de PerformanceCounter(s)
       CounterCreationData performanceCounter =
       new CounterCreationData(
       counterName: teller,
       counterHelp: "Om een telling te doen",
       counterType: PerformanceCounterType.NumberOfItems32);
                    
       //Definieer een Collectie
       CounterCreationDataCollection 
       performanceCounterCollectie = 
       new CounterCreationDataCollection();
                
       //Voeg de PerformanceCounter(s) 
       // toe aan de collectie
       performanceCounterCollectie.Add(performanceCounter);
                
       //Definieer de PerformanceCounter Category
       PerformanceCounterCategory.Create(
          categoryName: categorie,
          categoryHelp: "Een Test PerformanceCounter Categorie",
          categoryType: PerformanceCounterCategoryType.SingleInstance,
          counterData : performanceCounterCollectie);
                
       Console.WriteLine(
       "PerformanceCounter 
       Category {0} met Counter {1} is gecreëerd.", 
       categorie, teller);
     }
   }
   
   // VulPerformanceCounters
   static void VulPerformanceCounters(string categorie, string teller)
   {
     Console.WriteLine(
     "VulPerformanceCounter 
     Category {0} met Counter {1}.", 
     categorie, 
     teller);
     if (PerformanceCounterCategory.Exists(categorie))
     {
        PerformanceCounter performanceCounter = 
        new PerformanceCounter(categoryName:categorie, 
                               counterName :teller, 
                               readOnly    :false);
        // reset
        performanceCounter.RawValue = 0;
        for (int i = 1; i < 6; i++)
        {
           Console.WriteLine("Actie {0}", i);
           performanceCounter.IncrementBy(10);
           Thread.Sleep(1000);
        }
     }
   }   
 }
}

up

Laat een reactie achter

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *