퍼포먼스 카운터 알 아픈 디자인.
5044 단어 performance
응용 상황
PerformanceCounter는 프로세스 실례 이름을 통해 계수를 감시하지만, 이 실례 이름은 운영체제에서 실시간으로 동적으로 분배되며, 같은 이름의 프로세스가 하나만 있다면 처리하기 쉽다.같은 이름의 프로세스가 여러 개 있으면 비극적인 일이 일어난다. 같은 이름의 프로세스가 생성되고 닫히면 다른 같은 이름의 프로세스의 실례명에 영향을 줄 수 있다.따라서 해당 PerformanceCounter와 프로세스의 대응 관계가 완전히 혼란스러워집니다.(정말 이해가 안 돼. NET가 이걸 이루는데 왜 PID를 안 쓰는지)
현재 ams-p.exe 프로그램이 세 번씩 열려 있다고 가정하면 대응하는 프로세스의 실례명은 다음과 같다.
1)ams-p.exe [pid:7012]
2)ams-p.exe#1 [pid:7013]
3)ams-p.exe#2 [pid:7014]
실례명 윈도우즈 시스템이 실시간으로 분배하기 때문에 같은 이름의 프로세스 수량이 변화하는 것을 발견하면 대응하는 프로세스의 실례명도 변합니다.상기 상황에 따라 2가 닫힌 후에 그 실례에 대응하는 관계는 다음과 같다.
1)ams-p.exe [pid:7012]
3)ams-p.exe#1 [pid:7014]
이렇게 하면 3에 대응하는 실례명이 존재하지 않고 Performance Counter의 통계 오류를 초래할 수 있다. 같은 이름에 대응하는 프로세스의 수가 더 많고 중간에 프로세스가 닫히면 대량의 Performance Counter 통계와 프로세스의 대응 관계에 오류가 발생할 수 있다.
해결책
해결 방법이 있지만 방법은 모두 매우 고통스럽다. Process의 Exite 사건을 감시하고 퇴출 상황에 따라 실례명과 PID의 대응 관계를 조정한다. 그러나 이런 방식은 문제가 존재한다. 만약에 다른 응용 프로그램도 이 프로세스명이고 다른 채널을 통해 당신이 귀속된 Exite 사건을 제때 잡지 못하면 계수 오류가 발생하는 비극적인 사건이 발생할 수 있다.또 다른 해결 방법은 전면적인 것이다. 모든 Performance Counter를 실행하기 전에 현재 시스템의 이 이름의 프로세스 정보를 가져와 업로드하고 실시간 실례명과 PID 대응 관계를 구축한 다음Performance Counter를 실행한 후에 실례명에 대응하는 PID 계수를 기록한다.구체적인 코드는 다음과 같습니다.
class CPUCounter:IDisposable
{
public CPUCounter(string processName)
{
mProcessName = processName;
mTimer = new System.Threading.Timer(GetUsage, null, 1000, 1000);
}
private System.Threading.Timer mTimer;
private string mProcessName;
private Dictionary<int, float> mProcessCpuUsage = new Dictionary<int, float>();
private List<CounterItem> mCounters = new List<CounterItem>();
private Dictionary<string, int> mProcessIDs = new Dictionary<string, int>();
public float ProcessUsage(int pid)
{
float result = 0;
mProcessCpuUsage.TryGetValue(pid, out result);
return result;
}
private void OnCreateCounter(string processname)
{
CounterItem item = mCounters.Find(e => e.ProcessName == processname);
if (item == null)
{
item = new CounterItem();
item.Counter = new PerformanceCounter();
item.Counter.CategoryName = "Processor";
item.Counter.CounterName = "% Processor Time";
item.Counter.InstanceName = processname;
}
item.Enabled = true;
}
private void GetUsage(object state)
{
mProcessIDs.Clear();
Process[] ps = Process.GetProcessesByName(mProcessName);
List<CounterItem> disposeditems = new List<CounterItem>();
if (ps.Length == 1)
{
mProcessIDs.Add(mProcessName, ps[0].Id);
OnCreateCounter(mProcessName);
}
else
{
for (int i = 1; i < ps.Length; i++)
{
mProcessIDs.Add(mProcessName + "#" + i, ps[i].Id);
OnCreateCounter(mProcessName + "#" + i);
}
}
foreach (CounterItem item in mCounters)
{
if (item.Enabled)
{
mProcessCpuUsage[mProcessIDs[item.ProcessName]] = item.Counter.NextValue();
item.Enabled = false;
}
else
{
disposeditems.Add(item);
}
}
if(disposeditems.Count>0)
foreach (CounterItem item in disposeditems)
{
mCounters.Remove(item);
}
}
class CounterItem
{
public string ProcessName { get; set; }
public System.Diagnostics.PerformanceCounter Counter
{
get;
set;
}
public bool Enabled
{
get;
set;
}
}
public void Dispose()
{
if (mTimer != null)
mTimer.Dispose();
}
}
만약 더 좋은 방법이 있는 학우가 방심하지 않고 공유한다면
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
.NET 6 - AutoMapper 및 데이터 전송 개체(DTO) 🗺YouTube에서 전체 동영상을 볼 수 있습니다. 오늘 AutoMapper가 무엇이고 왜 필요한지 설명하는 것으로 시작할 수 있습니다. 이제 nuget 패키지가 설치되었으므로 automapper 구현 및 활용을 시작...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.