如何仅为记事本的所有运行实例查找内存(私有工作集)

Posted

技术标签:

【中文标题】如何仅为记事本的所有运行实例查找内存(私有工作集)【英文标题】:how to find memory (Private working set) for all running instance only of Notepad 【发布时间】:2015-08-19 07:46:59 【问题描述】:

好吧,我正在尝试为所有正在运行的 Notepad 实例获取内存(私有工作集)。 例如,假设 4 个记事本进程正在运行,现在我想要所有 4 个记事本实例消耗的总内存。

到目前为止,我已经尝试过为单人获取内存(私人工作集)

Process[] proc = Process.GetProcessesByName(Notepad);
foreach (var kl in proc)

   idnuml = kl.Id; // fetching pid for Notepad running instance.

PerformanceCounter PC = new PerformanceCounter( "Process", "Working Set -  Private", InstanceName);
memsize = Convert.ToInt32(PC.NextValue()) / 1024;

我不知道为什么 PerformanceCounter 不适用于 PID。 在每次迭代中,它能够检测不同实例的记事本 pid,但最终所有实例的工作集值相同。

请帮帮我。 提前感谢

【问题讨论】:

您确定要在找到的进程的 foreach 循环中添加更多代码吗?这就是为什么你得到相同的值而不是所有的值 即使在获得 PID 之后,最后我们也必须传递实例名称,即再次记事本。所以现在我又回到了展馆:'( 是的,但是,您的循环将 idnum1 设置为 id,但您最终只会将 idnum1 设置为循环中最后一个的值......所以它只会获取内存最后一项的用法。但是你也不使用 idnum1。 好的,似乎有些混乱,我发布的代码是部分的,我只想使用pid获取内存(私有工作集),因为我不知道PerformanceCounter是否真的是否接受pid,我尝试了几次使用pid搜索记事本内存,但出现异常,PerformanceCounter PC = new PerformanceCounter("Process", "Working Set - Private", InstanceName);现在告诉我是否可以使用 PID 找到工作集,如果是,请告诉我如何? 你没有提到......当你发布的代码不是实际运行的时候,它很难帮助你。 【参考方案1】:

我知道在here 之前已经回答了这个问题,但只是为了完整的工作代码,我发布了这个解决方案。请注意此代码基于链接链中M4N提交的方法:

public static long GetProcessPrivateWorkingSet64Size(int process_id)

  long process_size = 0;
  Process process = Process.GetProcessById(process_id);
  if (process == null) return process_size;
  string instanceName = GetProcessInstanceName(process.Id);
  var counter = new PerformanceCounter("Process", "Working Set - Private", instanceName, true);
  process_size = Convert.ToInt32(counter.NextValue()) / 1024;
  return process_size;


public static string GetProcessInstanceName(int process_id)

  PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
  string[] instances = cat.GetInstanceNames();
  foreach (string instance in instances)
  
    using (PerformanceCounter cnt = new PerformanceCounter("Process", "ID Process", instance, true))
    
       int val = (int)cnt.RawValue;
       if (val == process_id)
         return instance;
    
  
  throw new Exception("Could not find performance counter ");

另外,如果您想获取同一进程的多个实例的总内存,请使用上述方法和以下方法:

public static long GetPrivateWorkingSetForAllProcesses(string ProcessName)

  long totalMem = 0;
  Process[] process = Process.GetProcessesByName(ProcessName);
  foreach (Process proc in process)
  
    long memsize = GetProcessPrivateWorkingSet64Size(proc.Id);
    totalMem += memsize;
  
  return totalMem;

【讨论】:

【参考方案2】:

最后我得到了输出, 如果同一进程有多个实例.. 像记事本有 4 个实例,那么它将被视为 记事本 记事本#1 记事本#2 记事本#3

好吧,我正在发布我的代码,请人们在我关闭它之前自己调试并评论它。

public int m_PMmonitor()
    

        int count = 0,sum=0;
        int[] lm = new int[10];
        while (true)
        

            try
            
                Process[] proc = Process.GetProcessesByName(InstanceName);
                PerformanceCounter PC;
                sum = proc.Count();
                int k = 0;
                string pname;
                foreach (var pro in proc)
                

                    lm[count] = pro.Id;
                    if ((sum-1) == count)
                    
                        for (int i = 0; i <= (sum - 1); i++)
                        
                            Process p = Process.GetProcessById(lm[i]);
                            pname = p.ProcessName;
                            if (k == 0)
                            
                                PC = new PerformanceCounter("Process", "Working Set - Private", pname, true);
                                memsize = Convert.ToInt32(PC.NextValue()) / 1024;
                                Console.WriteLine(memsize);
                                k++;
                            
                            else
                            
                                PC = new PerformanceCounter("Process", "Working Set - Private", pname + "#" + (k).ToString(), true);
                                memsize = Convert.ToInt32(PC.NextValue()) / 1024;
                                Console.WriteLine(memsize);
                                k++;
                            
                            memsize = Convert.ToInt32(PC.NextValue()) / 1024;
                        
                    
                    count++;
                
                Thread.Sleep(800);
                return memsize ;
            
            catch (Exception e)
            
                Console.WriteLine(e.Message);

                Thread.Sleep(800);
                return 0;
            
        
    

【讨论】:

您已经在对Process.GetProcessesByName()的调用中获得了进程。无需再次通过Process.GetProcessById()获得进程。 此外,鉴于Process 类定义了WorkingSet 属性以及WorkingSet64,因此使用PerformanceCounter 是没有根据的。【参考方案3】:

好的,这是优化后的代码, 这是为了检查运行 N 实例的进程的“工作集 - 私有”。 比如假设 4 个记事本实例正在运行,那么它将被视为 记事本 记事本#1 记事本#2 记事本#3

注意:InstanceName 名称没有 extension ,您可以通过任务管理器对其进行验证。 "Working Set - Private" 将在编码时使用, 但要进行验证,您可以检查任务管理器中进程选项卡下的列内存(私有工作集)

 public int m_PMmonitor()
    

        int count = 0, sum = 0,buff=0;
        while (true)
        

            try
            
                Process[] proc = Process.GetProcessesByName(InstanceName);
                PerformanceCounter PC;
                sum = proc.Count();
                int k = 0;
                foreach (var pro in proc)
                
                            if (k == 0)
                            
                                PC = new PerformanceCounter("Process", "Working Set - Private", InstanceName, true);
                            
                            else
                            
                                PC = new PerformanceCounter("Process", "Working Set - Private", InstanceName + "#" + (k).ToString(), true);
                            
                            memsize = Convert.ToInt32(PC.NextValue()) / 1024;
                            Console.WriteLine(memsize);
                            buff = buff + memsize; //adding memsize of current running instance
                            PC.Dispose();
                            PC.Close();
                            count++;
                            k++;
                
                Thread.Sleep(800);
                return buff;
            
            catch (Exception e)
            
                Console.WriteLine(e.Message);

                Thread.Sleep(800);
                return 0;
            
            
        

【讨论】:

【参考方案4】:

您发布的代码只是痛苦。试试这个:

public int m_PMmonitor() 
    var processes = Process.GetProcessByName("notepad.exe");
    int memory = 0;

    foreach (var process in processes) 
        memory += process.WorkingSet / (1024^2);  // convert bytes to MB
    
return memory;

或者如果你喜欢 LINQ:

var memory = (from p in Process.GetProcessesByName("notepad.exe") select p.WorkingSet).Sum();

【讨论】:

'System.Diagnostics.Process.WorkingSet' 已过时:'"此属性已被弃用。请改用 System.Diagnostics.Process.WorkingSet64。go.microsoft.com/fwlink/?linkid=14202"' 1. 在没有解释的情况下发布编译器警告对任何人都没有任何好处。 2. PeakWorkingSet 和 WorkingSet 是两个完全不同的东西。 好吧,我正在寻找“Working Set - Private”, 有人请将我的问题编辑为,如何为同一进程的所有正在运行的实例查找(“工作集 - 私有”),例如为记事本的所有实例查找“工作集 - 私有”

以上是关于如何仅为记事本的所有运行实例查找内存(私有工作集)的主要内容,如果未能解决你的问题,请参考以下文章

Azure DevOps Build Pipeline:如何仅为更改的程序集增加程序集版本?

多线程简单实例真的需要synchronized么?

Java--数组

JMM内存模型

进程与线程

内存的工作集、高峰工作集、工作集增量、专用工作集、提交大小、页面缓冲池、非页面缓冲池 的区别