C# performance counter example

3 minute read

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace PerformanceCounterHelper
{
    public class PerformanceHelperClass
    {
        [DllImport("Kernel32.dll")]
        public static extern void QueryPerformanceCounter(ref long ticks);
        public static long GetCurrentTick()
        {
            long value = 0;
            QueryPerformanceCounter(ref value);
            return value;
        }
    }
    public interface IPerformanceDescription
    {
        string Category { get; }
        string Description { get; }
    }
    public class PerformanceCounter<T> where T : IPerformanceDescription, new()
    {
        /// <summary>
        /// Counter for counting total number of operations
        /// </summary>
        private PerformanceCounter m_totalOperations;
        /// <summary>
        /// Counter for counting number of operations per second
        /// </summary>
        private PerformanceCounter m_operationsPerSecond;
        /// <summary>
        /// Counter for counting duration averages
        /// </summary>
        private PerformanceCounter m_averageDuration;
        /// <summary>
        /// Counter for counting duration averages base
        /// </summary>
        private PerformanceCounter m_averageDurationBase;
        /// <summary>
        /// Creates a new performance counter category m_perfClass.Category if it does not already exists and adds some counters to it.
        /// </summary>
        /// 
        private T m_perfClass;
        private static readonly PerformanceCounter<T> m_instance = new PerformanceCounter<T>();
        public static PerformanceCounter<T> Instance
        {
            get { return m_instance; }
        }
        private PerformanceCounter()
        {
            m_perfClass = new T();
            if (!PerformanceCounterCategory.Exists(m_perfClass.Category))
            {
                CounterCreationDataCollection counters = new CounterCreationDataCollection();
                // 1. counter for counting totals: PerformanceCounterType.NumberOfItems32
                CounterCreationData totalOps = new CounterCreationData();
                totalOps.CounterName = "# operations executed";
                totalOps.CounterHelp = "Total number of operations executed";
                totalOps.CounterType = PerformanceCounterType.NumberOfItems32;
                counters.Add(totalOps);
                // 2. counter for counting operations per second: PerformanceCounterType.RateOfCountsPerSecond32
                CounterCreationData opsPerSecond = new CounterCreationData();
                opsPerSecond.CounterName = "# operations / sec";
                opsPerSecond.CounterHelp = "Number of operations executed per second";
                opsPerSecond.CounterType = PerformanceCounterType.RateOfCountsPerSecond32;
                counters.Add(opsPerSecond);
                // 3. counter for counting average time per operation: PerformanceCounterType.AverageTimer32
                CounterCreationData avgDuration = new CounterCreationData();
                avgDuration.CounterName = "average time per operation";
                avgDuration.CounterHelp = "Average duration per operation execution";
                avgDuration.CounterType = PerformanceCounterType.AverageTimer32;
                counters.Add(avgDuration);
                // 4. base counter for counting average time per operation: PerformanceCounterType.AverageBase
                CounterCreationData avgDurationBase = new CounterCreationData();
                avgDurationBase.CounterName = "average time per operation base";
                avgDurationBase.CounterHelp = "Average duration per operation execution base";
                avgDurationBase.CounterType = PerformanceCounterType.AverageBase;
                counters.Add(avgDurationBase);
                // create new category with the counters above
                PerformanceCounterCategory.Create(m_perfClass.Category, m_perfClass.Description, counters);
            }
            // create counters to work with
            m_totalOperations = new PerformanceCounter();
            m_totalOperations.CategoryName = m_perfClass.Category;
            m_totalOperations.CounterName = "# operations executed";
            m_totalOperations.MachineName = ".";
            m_totalOperations.ReadOnly = false;
            m_totalOperations.RawValue = 0;
            m_operationsPerSecond = new PerformanceCounter();
            m_operationsPerSecond.CategoryName = m_perfClass.Category;
            m_operationsPerSecond.CounterName = "# operations / sec";
            m_operationsPerSecond.MachineName = ".";
            m_operationsPerSecond.ReadOnly = false;
            m_operationsPerSecond.RawValue = 0;
            m_averageDuration = new PerformanceCounter();
            m_averageDuration.CategoryName = m_perfClass.Category;
            m_averageDuration.CounterName = "average time per operation";
            m_averageDuration.MachineName = ".";
            m_averageDuration.ReadOnly = false;
            m_averageDuration.RawValue = 0;
            m_averageDurationBase = new PerformanceCounter();
            m_averageDurationBase.CategoryName = m_perfClass.Category;
            m_averageDurationBase.CounterName = "average time per operation base";
            m_averageDurationBase.MachineName = ".";
            m_averageDurationBase.ReadOnly = false;
            m_averageDurationBase.RawValue = 0;
        }
        public void Initialize()
        {
        }
        /// <summary>
        /// Increments counters.
        /// </summary>
        /// <param name="ticks">The number of ticks the AverageTimer32 counter must be incremented by</param>
        public void DoPerformanceCounter(long ticks)
        {
            // simply increment the counters
            m_totalOperations.Increment();
            m_operationsPerSecond.Increment();
            m_averageDuration.IncrementBy(ticks); // increment the timer by the time cost of the operation
            m_averageDurationBase.Increment(); // increment base counter only by 1
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace PerformanceCounterHelper
{
    [ComVisible(true)]
    [Guid("xxxxxxxxxxxxxxxxxxxxxxxx")]
    public interface INetCmdQueueTimeCounter
    {
        void DoPerformanceCounter(long tick);
    }
    [ComVisible(true)]
    [Guid("xxxxxxxxxxxxxxxxxxxxxxxx")]
    public class NetCmdQueueTimeClass : INetCmdQueueTimeCounter
    {
        public class NetCmdPerformanceDescription : IPerformanceDescription
        {
            public string Category { get { return "Network Command Queue Time"; } }
            public string Description { get { return "Network Command Queue Time Counter"; } }
        }
        public NetCmdQueueTimeClass()
        {
            PerformanceCounter<NetCmdPerformanceDescription>.Instance.Initialize();
        }
        public void DoPerformanceCounter(long tick)
        {
            PerformanceCounter<NetCmdPerformanceDescription>.Instance.DoPerformanceCounter(tick);
        }
    }
}