2010-04-09 3 views
7

C#을 사용하여 개인 작업 집합을 계산하는 방법은 무엇입니까? 나는 taskmgr.exe와 대략 같은 숫자를 생산하는데 관심이 있습니다.개인 작업 집합 (메모리)을 계산하는 방법은 무엇입니까?

나는 프로세스 네임 스페이스를 사용하고 WorkingSet64PrivateMemorySize64과 같은 방법/데이터를 사용하고 있지만이 수치는 100MB 이상 떨어져 있습니다.

답변

23

매우 가변적 인 숫자이므로 계산할 수 없습니다. Windows 메모리 관리자는 페이지를 RAM 내부와 외부로 끊임없이 교환합니다. TaskMgr.exe는 성능 카운터에서이를 가져옵니다. 당신은 같은 수의 다음과 같이 얻을 수 있습니다 :

using System; 
using System.Diagnostics; 

class Program { 
    static void Main(string[] args) { 
     string prcName = Process.GetCurrentProcess().ProcessName; 
     var counter = new PerformanceCounter("Process", "Working Set - Private", prcName); 
     Console.WriteLine("{0}K", counter.RawValue/1024); 
     Console.ReadLine(); 
    } 
} 

는 숫자가 정말 많은 의미하지 않는다는 것을 조심 마십시오 다른 프로세스가 시작되면 삭제 및 RAM을 위해 경쟁 할 것이다.

+0

"숫자가 실제로 의미가 크지 않다"는 것을 어떻게 의미합니까? 이 수치는 프로세스가 다른 프로세스와 공유 할 수없는 메모리의 양을 나타내지는 않습니까? 저는 프로세스 "악의적 인"프로세스를 죽일 서비스를 만드는 것에 관심이 있습니다. "악의적 인"프로세스는 x MB 이상의 메모리를 사용하는 프로세스로 정의됩니다. 제가 사용하는 그림이 실제로 의미가 크지 않다면 서비스를 작성하는 것을 싫어할 것입니다. 무엇을 제안하겠습니까? – sholsapp

+0

아니, 숫자가 의미하는 것이 아닙니다. 다른 프로세스가 공유 할 수없는 프로세스에 의해 사용 된 가상 메모리의 양인 "Private Bytes"를 찾고 있습니다. –

+7

모든 것이 정확하다고 말하면서, 단지 'ProcessName'을 사용하여 일치하는 카운터 인스턴스를 조회하는 것만으로는 충분하지 않다고 덧붙이고 싶습니다. 동일한 프로세스 (예 : svchost.exe)가 여러 개있는 경우 카운터 이름은 "svchost # 1", "svchost # 2"등이됩니다. 또한 "ID 프로세스"카운터를 통해 일치해야합니다 프로세스 카테고리의'Process.ID'. –

0

여러 사용자가있을 수있는 프로세스에 대해 개인 작업 세트를 얻으려면 다음 단계를 수행해야합니다. 나는 GetNameToUseForMemory에서 적절한 프로세스 이름을 얻는 CurrentMemoryUsage을 호출한다. 내가 할 수있는 곳에서 결과를 필터링하는 경우에도이 루프가 느린 것으로 나타났습니다. 따라서 이름을 캐싱하기 위해 사전을 사용하는 GetNameToUseForMemory이 표시됩니다.

private static long CurrentMemoryUsage(Process proc) 
{ 
    long currentMemoryUsage; 
    var nameToUseForMemory = GetNameToUseForMemory(proc); 
    using (var procPerfCounter = new PerformanceCounter("Process", "Working Set - Private", nameToUseForMemory)) 
    { 
    //KB is standard 
    currentMemoryUsage = procPerfCounter.RawValue/1024; 
    } 
    return currentMemoryUsage; 
} 

private static string GetNameToUseForMemory(Process proc) 
{ 
    if (processId2MemoryProcessName.ContainsKey(proc.Id)) 
    return processId2MemoryProcessName[proc.Id]; 
    var nameToUseForMemory = String.Empty; 
    var category = new PerformanceCounterCategory("Process"); 
    var instanceNames = category.GetInstanceNames().Where(x => x.Contains(proc.ProcessName)); 
    foreach (var instanceName in instanceNames) 
    { 
    using (var performanceCounter = new PerformanceCounter("Process", "ID Process", instanceName, true)) 
    { 
     if (performanceCounter.RawValue != proc.Id) 
     continue; 
     nameToUseForMemory = instanceName; 
     break; 
    } 
    } 
    if(!processId2MemoryProcessName.ContainsKey(proc.Id)) 
    processId2MemoryProcessName.Add(proc.Id, nameToUseForMemory); 
    return nameToUseForMemory; 
} 
+0

"이전"프로세스가 종료되고 instanceName이 "다시 키잉"될 수 있으므로 값 캐싱이 작동하지 않습니다. http://blogs.technet.com/b/askperf/archive/2010/03/30/perfmon -identifying-processes-by-pid-instance-.aspx 대신 – Andre

+0

@Andre 맞습니다! 텍사스 –

관련 문제