.Net Runtime Library for Delphi
CNClrLib.Diagnostics Namespace

Example 1

The following code example demonstrates the use of the PerformanceCounter class to create and use an AverageCount64 counter type. The example creates categories, sets up counters, collects data from the counters, and calls the CounterSampleCalculator class to interpret the performance counter data. The intermediate and final results are displayed in the console window. For additional examples of other performance counter types, see the PerformanceCounterType enumeration.

program DiagnosticsExample; {$APPTYPE CONSOLE} {$R *.res} uses SysUtils, TypInfo, CNClrLib.EnumArrays, CNClrLib.Enums, CNClrLib.EnumTypes, CNClrLib.Diagnostics, CNClrLib.Host.Helper, CNClrLib.Host.Utils, CNClrLib.Core; var Console: _Console; samplesList: _ArrayList; avgCounter64Sample: _PerformanceCounter; avgCounter64SampleBase: _PerformanceCounter; // Output information about the counter sample. procedure OutputSample(s: _CounterSample); begin Console.WriteLine_14(#13#10 + '+++++++++++'); Console.WriteLine_14('Sample values - ' + #13#10); Console.WriteLine; Console.WriteLine_14(' BaseValue = ' + s.BaseValue.ToString); Console.WriteLine_14(' CounterFrequency = ' + s.CounterFrequency.ToString); Console.WriteLine_14(' CounterTimeStamp = ' + s.CounterTimeStamp.ToString); Console.WriteLine_14(' CounterType = ' + GetEnumName(System.TypeInfo(TPerformanceCounterType), OleEnumToOrd(PerformanceCounterTypeValues, s.CounterType))); Console.WriteLine_14(' RawValue = ' + s.RawValue.ToString); Console.WriteLine_14(' SystemFrequency = ' + s.SystemFrequency.ToString); Console.WriteLine_14(' TimeStamp = ' + s.TimeStamp.ToString); Console.WriteLine_14(' TimeStamp100nSec = ' + s.TimeStamp100nSec.ToString); Console.WriteLine_14('++++++++++++++++++++++'); end; // ++++++++//++++++++//++++++++//++++++++//++++++++//++++++++//++++++++//++++++++ // Description - This counter type shows how many items are processed, on average, // during an operation. Counters of this type display a ratio of the items // processed (such as bytes sent) to the number of operations completed. The // ratio is calculated by comparing the number of items processed during the // last interval to the number of operations completed during the last interval. // Generic type - Average // Formula - (N1 - N0) / (D1 - D0), where the numerator (N) represents the number // of items processed during the last sample interval and the denominator (D) // represents the number of operations completed during the last two sample // intervals. // Average (Nx - N0) / (Dx - D0) // Example PhysicalDisk\ Avg. Disk Bytes/Transfer // ++++++++//++++++++//++++++++//++++++++//++++++++//++++++++//++++++++//++++++++ function MyComputeCounterValue(s0, s1: _CounterSample): Single; var numerator, denomenator, counterValue: Single; begin numerator := s1.RawValue - s0.RawValue; denomenator := s1.BaseValue - s0.BaseValue; counterValue := numerator / denomenator; Exit(counterValue); end; function SetupCategory: Boolean; var PerformanceCounterCategory: _PerformanceCounterCategoryHelper; counterDataCollection: _CounterCreationDataCollection; averageCount64: _CounterCreationData; averageCount64Base: _CounterCreationData; begin PerformanceCounterCategory := CoPerformanceCounterCategoryHelper.CreateInstance; if not PerformanceCounterCategory.Exists('AverageCounter64SampleCategory') then begin counterDataCollection := CoCounterCreationDataCollection.CreateInstance; // Add the counter. averageCount64 := CoCounterCreationData.CreateInstance; averageCount64.CounterType := PerformanceCounterType_AverageCount64; averageCount64.CounterName := 'AverageCounter64Sample'; counterDataCollection.Add(averageCount64); // Add the base counter. averageCount64Base := CoCounterCreationData.CreateInstance; averageCount64Base.CounterType := PerformanceCounterType_AverageBase; averageCount64Base.CounterName := 'AverageCounter64SampleBase'; counterDataCollection.Add(averageCount64Base); // Create the category. PerformanceCounterCategory.Create_1('AverageCounter64SampleCategory', 'Demonstrates usage of the AverageCounter64 performance counter type.', PerformanceCounterCategoryType_SingleInstance, counterDataCollection); Exit(True); end else begin Console.WriteLine_14('Category exists - AverageCounter64SampleCategory'); Exit(False); end; end; procedure CreateCounters; begin // Create the counters. avgCounter64Sample := CoPerformanceCounter.CreateInstance('AverageCounter64SampleCategory', 'AverageCounter64Sample', False); avgCounter64SampleBase := CoPerformanceCounter.CreateInstance('AverageCounter64SampleCategory', 'AverageCounter64SampleBase', False); avgCounter64Sample.RawValue := 0; avgCounter64SampleBase.RawValue := 0; end; procedure CollectSamples(samplesList: _ArrayList); var r: _Random; j, value: Integer; begin r := CoRandom.CreateInstance(TClrDateTimeHelper.GetMillisecond(Now)); // Loop for the samples. for j := 0 to 99 do begin value := r.Next_1(1, 10); Console.Write_22(j.ToString + ' = ' + value.ToString); avgCounter64Sample.IncrementBy(value); avgCounter64SampleBase.Increment(); if j mod 10 = 9 then begin OutputSample(avgCounter64Sample.NextSample); samplesList.Add(avgCounter64Sample.NextSample); end else Console.WriteLine; Sleep(50); end; end; procedure CalculateResults(samplesList: _ArrayList); var CounterSampleCalculator: _CounterSampleCalculator; i: Integer; begin for i := 0 to samplesList.Count - 1 do begin // Output the sample. OutputSample(CoCounterSample.Wrap(samplesList[i])); OutputSample(CoCounterSample.Wrap(samplesList[i + 1])); CounterSampleCalculator := CoCounterSampleCalculator.CreateInstance; // Use .NET to calculate the counter value. Console.WriteLine_14('Computed counter value = ' + CounterSampleCalculator.ComputeCounterValue_1 (CoCounterSample.Wrap(samplesList[i]), CoCounterSample.Wrap(samplesList[i + 1])).ToString); // Calculate the counter value manually. Console.WriteLine_14('My computed counter value = ' + MyComputeCounterValue(CoCounterSample.Wrap(samplesList[i]), CoCounterSample.Wrap(samplesList[i + 1])).ToString); end; end; begin try Console := CoConsole.CreateInstance; samplesList := CoArrayList.CreateInstance; // If the category does not exist, create the category and exit. // Performance counters should not be created and immediately used. // There is a latency time to enable the counters, they should be created // prior to executing the application that uses the counters. // Execute this sample a second time to use the category. if SetupCategory then Exit; CreateCounters; CollectSamples(samplesList); CalculateResults(samplesList); except on E: Exception do begin Console.WriteLine_14(E.message); end; end; end.