简体   繁体   English

针对.NET生产服务中的内存泄漏

[英]Targetting memory leak in a .NET production service

I have a C#.NET service running in production. 我有一个在生产中运行的C#.NET服务。 The service functions as a TCP server to which clients register and make requests against. 该服务用作客户端注册和发出请求的TCP服务器。 In looking at the Task Manager, it appears to be leaking about 10MB/day. 在查看任务管理器时,它似乎泄漏了大约10MB /天。 I don't seem to notice these in dev (perhaps because of far less traffic and client activity). 我似乎没有注意到这些(也许是因为流量和客户活动少得多)。 In searching around I've read that the Task Manager can be seriously wrong, but I'm not sure how accurate this is or in what circumstances the TM would display incorrect information. 在搜索时我已经读到任务管理器可能严重错误,但我不确定这是多么准确或在什么情况下TM会显示不正确的信息。

To solve this problem I need to more closely monitor memory consumption. 要解决这个问题,我需要更密切地监控内存消耗。 The problem is that the leak only seems to appear in production, where the deployed service was built for Release. 问题是泄漏似乎只出现在生产中,其中部署的服务是为Release构建的。 Also since it's a service that can't be run directly be VS with an attached profiler/debugging, I'm not sure how to best pinpoint the problem with something more precise than TM. 此外,因为它是一个无法直接运行的服务,带有附加的分析器/调试,我不知道如何用比TM更精确的东西来最好地查明问题。

Any group wisdom would be much appreciated, thanks. 任何群体智慧都会非常感激,谢谢。

EDIT: 编辑:

  • I've added perfmon counters for the privates bytes of the service (7MB to start out) as well as CLR mem in all heaps (30MB to start out) 我已经为服务的私有字节添加了perfmon计数器(7MB开始)以及所有堆中的CLR mem(30MB开始)
  • Task manager says the total memory to be ~37MB so this seems to make sense 任务经理说总内存大约为37MB,所以这似乎是有道理的
  • The first part of this is to let the service go for a day and check out my counters again. 第一部分是让服务去一天,然后再次检查我的柜台。

If my private bytes get huge but CLR mem is roughly static this would indicate an unmanaged leak. 如果我的私有字节变得很大但CLR内存大致是静态的,这将表明一个非托管泄漏。 If both get huge then it's a managed leak. 如果两者都变得巨大,那么它就是一个有管理的泄漏。

Thanks guys. 多谢你们。

Your first task is figuring out if the process is leaking memory. 您的第一个任务是确定进程是否泄漏内存。 You can do this with perfmon measuring the Private Bytes http://www.goldstarsoftware.com/papers/CapturingVirtualBytesToALogFile.pdf 您可以使用perfmon测量私有字节http://www.goldstarsoftware.com/papers/CapturingVirtualBytesToALogFile.pdf

If the graph is consistently rising (for say half an hour ) you have a memory leak. 如果图表一直在上升(例如半小时),则会出现内存泄漏。 You can then use other counters to figure out if this is a .NET leak (.NET memory) though this is unlikely. 然后,您可以使用其他计数器来确定这是否是.NET泄漏(.NET内存),尽管这不太可能。 I find that in most of these cases, there is a COM component that is being invoked but not released. 我发现在大多数情况下,有一个COM组件正在被调用但未被释放。

If you truly have a memory leak (and this isn't just variable memory usage)- the process will shutdown with an out of memory exception after running for a while. 如果你确实有内存泄漏(这不仅仅是可变内存使用) - 运行一段时间后,进程将因内存不足而关闭。

You need one of the below MemoryProfilers in order to monitor it; 您需要以下MemoryProfilers之一来监控它;

http://www.jetbrains.com/profiler/ http://www.jetbrains.com/profiler/

http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/ http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/

There are other choices but these are very capable and you can profile remote application's memory with them (at least JetBrains's solution handles that) 还有其他选择,但这些选项非常强大,您可以使用它们分析远程应用程序的内存(至少JetBrains的解决方案处理它)

Follow this guide: http://blogs.msdn.com/b/tess/archive/2008/03/25/net-debugging-demos-lab-7-memory-leak.aspx 请遵循以下指南: http//blogs.msdn.com/b/tess/archive/2008/03/25/net-debugging-demos-lab-7-memory-leak.aspx

It goes over exactly what you're describing, a memory leak in production. 它完全超出了你所描述的内容,即生产中的内存泄漏。 As was mentioned you have to first determine whether it's unmanaged code or managed code that's leaking using perfmon and Private Bytes. 如前所述,您必须首先确定它是使用perfmon和Private Bytes泄漏的非托管代码还是托管代码。

In general make sure for networking objects you're wrapping them in using statements so that they're properly disposed. 一般来说,确保使用语句包装它们的网络对象,以便正确处理它们。

A workflow I often use for managed memory leaks is to start the server on a test machine, hit it with a known amount of connections (say 123,456 connections). 我经常用于托管内存泄漏的工作流程是在测试计算机上启动服务器,使用已知数量的连接(例如123,456个连接)命中它。 Then take a memory snapshot by going to task manager and right clicking on the process name and selecting 'create dump'. 然后通过转到任务管理器并右键单击进程名称并选择“create dump”来获取内存快照。 Open this dump with WinDBG and SOS and run the command !dumpheap -stat. 使用WinDBG和SOS打开此转储并运行命令!dumpheap -stat。 Look for objects that have a multiple of 123,456 instances. 查找具有123,456个实例的多个对象。 Should these objects still be in memory? 这些物体是否仍然在记忆中? If not run a !gcroot on an instance of those objects to find why it's still in memory. 如果没有在这些对象的实例上运行!gcroot来查找它仍然在内存中的原因。

  1. Get a dump of the memory when its in a leak state using the Task Manager right click on the process and select create dump file. 使用任务管理器右键单击进程并选择创建转储文件,在内存处于泄漏状态时获取内存转储。 You can also use ProcDump which gives you more options. 您还可以使用ProcDump ,它为您提供更多选项。

  2. Use SOS Extensions in either WinDebug or Visual Studio to inspect the memory. WinDebug或Visual Studio中使用SOS Extensions检查内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM