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

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

问题描述

我有一段代码,使用静态方法的 Process.GetProcessesByName(字符串,字符串),这个运行在许多计算机(几千)和我注意到这是一个重大的内存泄漏的原因



我跑蚂蚁内存分析器它告诉我,我的大多数内存被采取的字符串,包含类似%空闲时间,处理器信息strage值的字符串,和缓存错误/秒。我承认这些字符串作为可能是性能计数器的一部分,该计划,问题是我没有程序中的任何性能计数器。



进一步挖掘发现那些字符串在由PerformanceCounterLib保持哈希表这是由储存在该PerformanceCounterLib类的内部静态部件(这本身是内部)的内部ANOTHER哈希表保持保持



挖掘更深进了兔子洞,我发现,Process.GetProcesesByName使用PerformanceCounterLib得到一个远程计算机上运行的进程列表,并且为每个远程计算机的另一个PerformanceCounterLib实例被创建和引用的静态内部PerformanceCounterLib的变量。每个这些实例认为,我发现被堵塞我的记忆(他们每个人的300-700是KB之间,这就意味着它堵塞我的大对象堆)串的哈希表。



我没有找到一个方法来删除那些未使用的PerformanceCounterLib情况下,他们都是内部和用户对他们的访问权限。



我怎样才能解决我的记忆问题?这是非常糟糕的,我计划在24小时内打5GB(我的服务器的限制)



修改的:添加一段代码(未测试)应该重现该问题。澄清:

  /// computerNames是,你有机会获得
公开名单<的计算机列表;串> GetProcessesOnAllComputers(列表<串GT; computerNames)
{
VAR的结果=新的List<串GT;();
的foreach(在computernames串COMPNAME)
{
过程[] =流程Process.GetProcesses(COMPNAME); //与每一个获得在远程计算机
串processString = processes.Aggregate(新的StringBuilder()方法的过程发生时,(SB,S)=> sb.Append(';')。追加(S) ,SB => sb.ToString());
result.Add(processString);
的foreach(在流程变种P)
{
p.Close();
p.Dispose();
}
流程= NULL;
}
}


解决方案

您可以调用 PerformanceCounter.CloseSharedResources



在内部,这个调用 PerformanceCounterLib.CloseAllLibraries ,它做什么,它听起来就像



我建议确保您每次调用这个时候没有电话 GetProcessesByName 都在进步,因为它看起来像有可能会有一些竞争条件在 PerformanceCounterLib ,你不想去招惹。



即有 libraryTable 称为共享变量则假定继续有效的一个方法,是检查一次,但可能是由 CloseAllLibraries 在任何时候 - 所以它的决然不是线程安全的。


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.

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.

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).

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).

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

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

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;
    }
}

解决方案

You can call PerformanceCounter.CloseSharedResources.

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

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.

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(字符串,字符串)内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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