Process.GetProcessesByName(String, String) 内存泄漏 [英] Process.GetProcessesByName(String, String) Memory Leak

查看:32
本文介绍了Process.GetProcessesByName(String, String) 内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段代码使用静态方法获取远程计算机上的进程列表Process.GetProcessesByName(String, String),这在很多计算机(几千台)上运行,我注意到这是一个主要内存泄漏的原因.

I have a piece of code that gets a list of processes on a remote computer using the static method Process.GetProcessesByName(String, String), this runs on a lot of computers (a few thousands) and I've noticed it's a cause of a major memory leak.

我运行了 ANTS 内存分析器,它告诉我我的大部分内存都被字符串占用,字符串包含诸如%空闲时间"、处理器信息"和缓存故障/秒"之类的策略值.我已经认识到这些字符串可能是程序中性能计数器的一部分,问题是我在程序中没有任何性能计数器.

I ran ANTS memory profiler which told me that most of my memory is taken by strings, strings containing strage values like "% Idle Time", "Processor Information", and "Cache Faults/sec". I've recognized those strings as probably being a part of Performance Counters in the program, the problem is I don't have any performance counters in the program.

深入挖掘发现,这些字符串保存在 PerformanceCounterLib 保存的哈希表中,而 PerformanceCounterLib 保存在另一个哈希表中,该哈希表存储在 PerformanceCounterLib 类(它本身是内部的)的内部静态成员中.

Digging deeper found out those strings are held in hashtables that are held by PerformanceCounterLib which are held by ANOTHER hashtable that is stored inside an internal static member of the PerformanceCounterLib class (which in itself is internal).

深入研究兔子洞,我发现 Process.GetProcesesByName 使用 PerformanceCounterLib 来获取在远程计算机上运行的进程列表,并且为每台远程计算机创建另一个 PerformanceCounterLib 实例并在静态内部变量中引用PerformanceCounterLib 的.每个实例都保存着我发现的字符串哈希表阻塞了我的记忆(每个字符串都在 300-700 kb 之间,这意味着它阻塞了我的大对象堆).

Digging even deeper into the rabbit hole, I've found out that Process.GetProcesesByName uses PerformanceCounterLib to get the process list running on a distant computer and that for each remote computer another PerformanceCounterLib instance is created and referenced in the static internal variable of PerformanceCounterLib. Each of those instances hold that hashtable of strings that I found out is clogging my memory (each of them is between 300-700 kb, meaning it's clogging up my Large Object Heap).

我没有找到删除那些未使用的 PerformanceCounterLib 实例的方法,它们都是内部的,用户无法访问它们.

I did not find a way to delete those unused PerformanceCounterLib instances, they are all internal and the user has no access to them.

我该如何解决我的记忆问题?这真的很糟糕,我的程序在 24 小时内达到了 5GB(我的服务器限制).

How can I fix my memory problem? This is REALLY bad, my program hits 5GB (my server's limit) within 24 hours.

EDIT:添加了一段应重现问题的代码(未测试).澄清:

EDIT: added a piece of code (not tested) that should reproduce the problem. For clarification:

/// computerNames is a list of computers that you have access to
public List<string> GetProcessesOnAllComputers(List<string> computerNames)
{
    var result = new List<string>();
    foreach(string compName in computernames)
    {
        Process[] processes = Process.GetProcesses(compName); // Happens with every     method that gets processes on a remote computer
        string processString = processes.Aggregate(new StringBuilder(), (sb,s) => sb.Append(';').Append(s), sb => sb.ToString());
        result.Add(processString);
        foreach (var p in processes)
        {
            p.Close();
            p.Dispose();
        }
        processes = null;
    }
}

推荐答案

您可以拨打 PerformanceCounter.CloseSharedResources.

在内部,这会调用 PerformanceCounterLib.CloseAllLibraries,它的作用就像听起来一样.

Internally, this calls PerformanceCounterLib.CloseAllLibraries, which does what it sounds like.

我建议您确保在没有调用 GetProcessesByName 的时候调用它,因为看起来 PerformanceCounterLib 中可能存在一些竞争条件> 你不想激怒.

I'd advise making sure that you call this at a time when no calls to GetProcessesByName are in progress, since it looks like there may be some race conditions inside PerformanceCounterLib that you don't want to provoke.

即有一个名为 libraryTable 的共享变量被检查一次,然后假定在一个方法中继续有效,但可能随时被 CloseAllLibraries 清除 - 所以它绝对不是线程安全.

i.e. there's a shared variable called libraryTable that is checked once then assumed to continue to be valid in one method, and yet might be cleared by CloseAllLibraries at any time - so its decidedly not thread safe.

这篇关于Process.GetProcessesByName(String, String) 内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆