본문 바로가기
C#

[C#] PerformanceCounter, PerformanceCounterCategory

by DANEW 2023. 10. 28.

PerformanceCounterCategory 클래스

 

PerformanceCounterCategory 클래스 (System.Diagnostics)

성능 카운터의 범주를 정의하는 성능 개체를 나타냅니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public sealed class PerformanceCounterCategory
    {
        public PerformanceCounterCategory();
        public PerformanceCounterCategory(string categoryName);
        public PerformanceCounterCategory(string categoryName, string machineName);
 
        public string CategoryHelp { get; }
 
        public string CategoryName { get; set; }
        public PerformanceCounterCategoryType CategoryType { get; }
        public string MachineName { get; set; }
 
        public static PerformanceCounterCategory[] GetCategories();
        public static PerformanceCounterCategory[] GetCategories(string machineName);
 
        // public static PerformanceCounterCategory Create(string categoryName, string categoryHelp, string counterName, string counterHelp);
        public static PerformanceCounterCategory Create(string categoryName, string categoryHelp, PerformanceCounterCategoryType categoryType, string counterName, string counterHelp);
        // public static PerformanceCounterCategory Create(string categoryName, string categoryHelp, CounterCreationDataCollection counterData);
        public static PerformanceCounterCategory Create(string categoryName, string categoryHelp, PerformanceCounterCategoryType categoryType, CounterCreationDataCollection counterData);              
       
        public static void Delete(string categoryName);
 
        public static bool Exists(string categoryName, string machineName);
        public static bool Exists(string categoryName);
        public static bool CounterExists(string counterName, string categoryName);
        public static bool CounterExists(string counterName, string categoryName, string machineName);
        public static bool InstanceExists(string instanceName, string categoryName);
        public static bool InstanceExists(string instanceName, string categoryName, string machineName);
       
        public bool CounterExists(string counterName);
        public bool InstanceExists(string instanceName);
 
        public PerformanceCounter[] GetCounters();
        public PerformanceCounter[] GetCounters(string instanceName);
 
        public string[] GetInstanceNames();
 
        public InstanceDataCollectionCollection ReadCategory();
    }
}
namespace System.Diagnostics
{
    public enum PerformanceCounterCategoryType
    {
        Unknown = -1,
        SingleInstance = 0,
        MultiInstance = 1
    }
}

PerformanceCounter 클래스

namespace System.Diagnostics
{
    public sealed class PerformanceCounter : Component, ISupportInitialize
    {
        // public static int DefaultFileMappingSize;
 
        public PerformanceCounter();
        public PerformanceCounter(string categoryName, string counterName);
        public PerformanceCounter(string categoryName, string counterName, string instanceName);
        public PerformanceCounter(string categoryName, string counterName, bool readOnly);
        public PerformanceCounter(string categoryName, string counterName, string instanceName, string machineName);
        public PerformanceCounter(string categoryName, string counterName, string instanceName, bool readOnly);
 
        public bool ReadOnly { get; set; }
 
        public string MachineName { get; set; }
        public string CategoryName { get; set; }
        public string InstanceName { get; set; }
        public PerformanceCounterInstanceLifetime InstanceLifetime { get; set; }
        public string CounterName { get; set; }
        public PerformanceCounterType CounterType { get; }
        public string CounterHelp { get; }
       
        public long RawValue { get; set; }
        public long Increment();
        public long IncrementBy(long value);
        public long Decrement();
 
        public float NextValue();
        public CounterSample NextSample();
 
        public void BeginInit();
        public void EndInit();
        public void Close();
        public static void CloseSharedResources();
        protected override void Dispose(bool disposing);
    }
}
namespace System.Diagnostics
{
    public enum PerformanceCounterInstanceLifetime
    {
        Global = 0,
        Process = 1
    }
}
namespace System.Diagnostics
{
    public enum PerformanceCounterType
    {
        NumberOfItemsHEX32 = 0,                
        NumberOfItemsHEX64 = 256,  
        NumberOfItems32 = 65536,                
        NumberOfItems64 = 65792,    
        CounterDelta32 = 4195328,              
        CounterDelta64 = 4195584,
        SampleCounter = 4260864,                
        CountPerTimeInterval32 = 4523008,      
        CountPerTimeInterval64 = 4523264,
        RateOfCountsPerSecond32 = 272696320,    
        RateOfCountsPerSecond64 = 272696576,
        RawFraction = 537003008,                
        CounterTimer = 541132032,              
        Timer100Ns = 542180608,                
        SampleFraction = 549585920,            
        CounterTimerInverse = 557909248,
        Timer100NsInverse = 558957824,
        CounterMultiTimer = 574686464,
        CounterMultiTimer100Ns = 575735040,
        CounterMultiTimerInverse = 591463680,
        CounterMultiTimer100NsInverse = 592512256,
        AverageTimer32 = 805438464,
        ElapsedTime = 807666944,
        AverageCount64 = 1073874176,
        SampleBase = 1073939457,
        AverageBase = 1073939458,
        RawBase = 1073939459,
        CounterMultiBase = 1107494144
    }
}

CounterCreationDataCollection 클래스

 

CounterCreationDataCollection 클래스 (System.Diagnostics)

CounterCreationData 개체의 강력한 형식의 컬렉션을 제공합니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public class CounterCreationDataCollection : CollectionBase
    {
        public CounterCreationDataCollection();
        public CounterCreationDataCollection(CounterCreationDataCollection value);
        public CounterCreationDataCollection(CounterCreationData[] value);
 
        public CounterCreationData this[int index] { get; set; }
        public int IndexOf(CounterCreationData value);
 
        public bool Contains(CounterCreationData value);
 
        public int Add(CounterCreationData value);
        public void AddRange(CounterCreationData[] value);
        public void AddRange(CounterCreationDataCollection value);
        public void Insert(int index, CounterCreationData value);
 
        public virtual void Remove(CounterCreationData value);
 
        public void CopyTo(CounterCreationData[] array, int index);
 
        protected override void OnValidate(object value);
    }
}

CounterCreationData 클래스

 

CounterCreationData 클래스 (System.Diagnostics)

사용자 지정 카운터의 카운터 형식, 이름 및 도움말 문자열을 정의합니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public class CounterCreationData
    {
        public CounterCreationData();
        public CounterCreationData(string counterName, string counterHelp, PerformanceCounterType counterType);
 
        public PerformanceCounterType CounterType { get; set; }
 
        public string CounterName { get; set; }
        public string CounterHelp { get; set; }
    }
}

InstanceDataCollectionCollection 클래스

 

InstanceDataCollectionCollection 클래스 (System.Diagnostics)

InstanceDataCollection 개체의 강력한 형식의 컬렉션을 제공합니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public class InstanceDataCollectionCollection : DictionaryBase
    {
        // public InstanceDataCollectionCollection();
 
        public InstanceDataCollection this[string counterName] { get; }
       
        public ICollection Keys { get; }
        public ICollection Values { get; } 
        public bool Contains(string counterName); 
        public void CopyTo(InstanceDataCollection[] counters, int index);
    }
}

InstanceDataCollection 클래스

 

InstanceDataCollection 클래스 (System.Diagnostics)

InstanceData 개체의 강력한 형식의 컬렉션을 제공합니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public class InstanceDataCollection : DictionaryBase
    {
        // public InstanceDataCollection(string counterName);
 
        public InstanceData this[string instanceName] { get; }
 
        public string CounterName { get; }
 
        public ICollection Keys { get; }
        public ICollection Values { get; }
        public bool Contains(string instanceName);
        public void CopyTo(InstanceData[] instances, int index);
    }
}

InstanceData 클래스

 

InstanceData 클래스 (System.Diagnostics)

성능 카운터 샘플과 관련된 인스턴스 데이터를 보유합니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public class InstanceData
    {
        public InstanceData(string instanceName, CounterSample sample);
 
        public string InstanceName { get; }
        public CounterSample Sample { get; }
        public long RawValue { get; }
    }
}

CounterSample 클래스

 

CounterSample 구조체 (System.Diagnostics)

성능 카운터의 원시 데이터를 보유하는 구조체를 정의합니다.

learn.microsoft.com

namespace System.Diagnostics
{
    public struct CounterSample
    {
        public static CounterSample Empty;
 
        public CounterSample(long rawValue, long baseValue, long counterFrequency, long systemFrequency, long timeStamp, longtimeStamp100nSec, PerformanceCounterType counterType);
        public CounterSample(long rawValue, long baseValue, long counterFrequency, long systemFrequency, long timeStamp, longtimeStamp100nSec, PerformanceCounterType counterType, long counterTimeStamp);
 
        public long TimeStamp { get; }
        public long TimeStamp100nSec { get; }
        public long CounterTimeStamp { get; }
        public long CounterFrequency { get; }
        public long SystemFrequency { get; }
        public long BaseValue { get; }
        public long RawValue { get; }
        public PerformanceCounterType CounterType { get; }
 
        public static float Calculate(CounterSample counterSample);
        public static float Calculate(CounterSample counterSample, CounterSample nextCounterSample);        
 
        public bool Equals(CounterSample sample);
        public override bool Equals(object o);
        public override int GetHashCode();
 
        public static bool operator ==(CounterSample a, CounterSample b);
        public static bool operator !=(CounterSample a, CounterSample b);
    }
}

성능 카운터

- 응용 프로그램, 시스템의 현재 상태를 파악하기 위한 실시간적인 접근 방식
 * 응용 프로그램의 성능 카운터(Performance Counter) 
 * 카운터를 실시간으로 감시하는 MS 관리 콘솔(Microsoft Management Console, MMC) 스냅인들
- 성능 카운터는 여러가지 범주(성능 개체, Performance Object)로 나뉘어져 있음
 * System
 * Processor
 * .NET CLR 메모리
- 하나의 범주 안에 여러개의 인스턴스가 존재 할 수 있음


사용 가능한 성능 카운터 열거

namespace Practice
{
    class Program
    {
        public static void Main(string[] arg)
        {
            PerformanceCounterCategory[] pcca = PerformanceCounterCategory.GetCategories();
 
            // 각 범주(카테고리)별로 열거
            foreach (PerformanceCounterCategory pcc in pcca)
            {
                Console.WriteLine("범주: " + pcc.CategoryName);
 
                string[] pccInstances = pcc.GetInstanceNames();
 
                // 인스턴스가 하나도 없는 경우
                // 범주 자체에 대한 카운터들을 표시
                if (pccInstances.Length == 0)
                {
                    foreach (PerformanceCounter pc in pcc.GetCounters())
                    {
                        Console.WriteLine("  카운터: " + pc.CounterName);
                    }
                }
 
                // 인스턴스가 하나 이상인 경우
                else
                {
                    // 각 인스턴스별로 열거
                    foreach (string pccInstance in pccInstances)
                    {
                        Console.WriteLine("  인스턴스: " + pccInstance);
 
                        // 인스턴스가 실제 존재하는지 확인해야함
                        // 이름은 존재하는데, 실제 내용이 없는 경우가 있음
                        if (pcc.InstanceExists(pccInstance))
                        {
                            foreach (PerformanceCounter pc in pcc.GetCounters(pccInstance))
                            {
                                Console.WriteLine("    카운터: " + pc.CounterName);
                            }
                        }
                    }
                }
            }
        }
    }
}

- 현재 컴퓨터의 모든 성능 카운터를 열거
- 위 예제는 엄청나게 긴 출력 결과를 포함, InstaceExists의 구현이 효율적이지 않아 오랜 시간이 걸림
- 실제 시스템에서 카운터들에 관한 자세한 정보는 꼭 필요할 때에만 조회해야 함

반응형

성능 카운터 자료 읽기

- PerformanceCounter 객체를 생성
 * 생성자 - 범주 이름, 카운터 이름, 인스턴스 지정
- NextValue: float
- NextSample: ConuterSample (좀 더 자세한 정보)

using (PerformanceCounter mpc = new PerformanceCounter("Processor", "% Processor Time", "_Total"))
{
    Console.WriteLine($"{mpc.CategoryName} - {mpc.InstanceName} - {mpc.CounterName} : {mpc.NextValue()}");
}
string processName = Process.GetCurrentProcess().ProcessName;
using (PerformanceCounter mpc = new PerformanceCounter("Process", "Private Bytes", processName))
{
    Console.WriteLine($"{mpc.CategoryName} - {mpc.InstanceName} - {mpc.CounterName} : {mpc.NextValue().ToString("F0")}");
}

- 성능 카운터가 변했을 때 통지를 받고 싶다면 폴링(Polling), 주기적으로 값을 점검해야 함

namespace Practice
{
    class Program
    {
        public static void Main(string[] arg)
        {
            EventWaitHandle stopper = new ManualResetEvent(false);
 
            new Thread(() => Monitor("Processor", "% Processor Time", "_Total", stopper)).Start();
            new Thread(() => Monitor("LogicalDisk", "% Idle Time", "C:", stopper)).Start();
 
            var defaultColor = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("Monitoring... Press any key to exit...");
            Console.ForegroundColor = defaultColor;
 
            Console.ReadKey(true);
            stopper.Set();
        }
 
        static void Monitor (string category, string counter, string instance, EventWaitHandle stopper)
        {
            // 카테고리 체크
            if (!PerformanceCounterCategory.Exists (category))
            {
                throw new InvalidOperationException("해당 범주 없음");
            }
 
            // 카운터 체크
            if (!PerformanceCounterCategory.CounterExists(counter, category))
            {
                throw new InvalidOperationException("해당 카운터 없음");
            }
 
            // 인스턴스 체크
            if (instance == null)
            {
                instance = "";
            }
 
            if (instance != "" && !PerformanceCounterCategory.InstanceExists(instance, category))
            {
                throw new InvalidOperationException("해당 인스턴스 없음");
            }
 
            // 비교할 기존 값
            float lastValue = 0f;
 
            // 체크 반복 딜레이
            const int delay = 5000;
 
            using (PerformanceCounter pc = new PerformanceCounter(category, counter, instance))
            {
                // 딜레이 간격으로 실행
                while (!stopper.WaitOne (delay, false))
                {
                    float value = pc.NextValue();
 
                    string labelString = $"{pc.CategoryName.PadLeft(15)} - {pc.InstanceName.PadLeft(10)} - {pc.CounterName.PadLeft(10)}";
 
                    // 기존 값과 측정 값이 서로 다르다면 출력
                    if (value != lastValue)
                    {
                        Console.WriteLine($"{labelString}: {value}");
                        lastValue = value;
                    }
                }
            }
        }
    }
}

커스텀 성능 카운터 작성 및 성능 기록

- 생성 : CounterCreationDataCollection 통해 카운터들을 기록, 한번에 범주로 만듬
             PerformanceCounterCategory.Create 통해 추가
- 수정: 기존 범주를 삭제하고 수정해서 한번에 다시 올려야 함
- 삭제: PerformanceCounterCategory.Delete
- 기록: 인스턴스화, Readonly 속성을 false로 바꾸고 RawValue를 수정

string category = "Custom Performance Counter";
 
string counterOne = "Counter One";
string counterTwo = "Counter Two";
 
// 추가
if (!PerformanceCounterCategory.Exists(category))
{
    CounterCreationDataCollection ccdc = new CounterCreationDataCollection();
 
    ccdc.Add(new CounterCreationData(counterOne, "첫번째 커스텀 카운터", PerformanceCounterType.NumberOfItems32));
    ccdc.Add(new CounterCreationData(counterTwo, "두번째 커스텀 카운터", PerformanceCounterType.NumberOfItems32));
 
    PerformanceCounterCategory.Create(category, "커스텀 퍼포먼스 카운터", PerformanceCounterCategoryType.SingleInstance, ccdc);
}
 
// 갱신
using (PerformanceCounter pc = new PerformanceCounter(category, counterOne))
{
    pc.ReadOnly = false;
    pc.RawValue = 1000;     // 1000
    pc.Increment();         // 1001
    pc.IncrementBy(10);     // 1011
    pc.Decrement();         // 1010
 
    Console.WriteLine(pc.NextValue());
}
 
// 삭제
if (PerformanceCounterCategory.Exists(category))
{
    PerformanceCounterCategory.Delete(category);
}
반응형

'C#' 카테고리의 다른 글

[C#] Stream  (0) 2023.11.17
[C#] Task  (0) 2023.11.06
[C#] Thread  (0) 2023.11.01
[C#] Stopwatch  (0) 2023.10.30
[C#] EventLog (Windows 이벤트 로그)  (0) 2023.10.26
[C#] StackTrace, StackFrame  (0) 2023.10.24
[C#] Debugger  (0) 2023.10.22
[C#] Contract, Code Contracts(코드 계약)  (0) 2023.10.20