Tracking Down a .NET Windows Service Memory Leak

2019-04-05 02:20发布

Before installing my windows service in production, I was looking for reliable tests that I can perform to make sure my code doesn't contain memory leaks. However, All what I can find on the net was using task manager to look at used memory or some paid memory profiler tools.

From my understanding, looking at the task manager is not really helpful and cannot confirm the memory leakage (in case, there is).

  1. How to confirm whether there is a memory leak or not?

  2. Is there any free tools to find the source of memory leaks?

Note: I'm using .Net Framework 4.6 and Visual Studio 2015 Community

7条回答
我只想做你的唯一
2楼-- · 2019-04-05 02:29

If you use Entity Framework and a DI pattern, perhaps using Castle Windsor, you can easily get memory leaks.

The main thing to do is use the using( ){ } statement where-ever you can to automatically mark objects as disposed.

Also, you want to turn off automatic tracking on Entity Framework where you are only reading and not writing. Best to isolate your writes, use a using() {} at this point, get a dbContext (with tracking on), write your data.

If you want to investigate what is on the heap. The best tool I've used is RedGate ANTS http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/solving-memory-problems/getting-started not cheap but it works.

However, by using the using() {} pattern where-ever you can (don't make a static or singleton DbContext and never have one context in a massive loop of updates, dispose of them as often as you can!) then you find memory isn't often an issue.

Hope this helps.

查看更多
Lonely孤独者°
3楼-- · 2019-04-05 02:31

Although managed code implies no direct memory management, you still have to manage your instances. Those instances 'claim' memory. And it is all about the usage of these instances, keeping them alive when you don't expect them to be.

Just one of many examples: wrong usage of disposable classes can result in a lot of instances claiming memory. For a windows service, a slow but steady increase of instances can eventually result in to much memory usage.

Yes, there is a tool to analyze memory leaks. It just isn't free. However you might be able to identify your problem within the 7 day trail.

I would suggest to take a loot at the .NET Memory Profiler.

It is great to analyze memory leaks during development. It uses the concept of snapshots to compare new instances, disposed instances etc. This is a great help to understand how your service uses its memory. You can then dig deeper into why new instances get created or are kept alive.

Yes, you can test to confirm whether memory leaks are introduced. However, just out-of-the box this will not be very useful. This is because no one can anticipate what will happen during runtime. The tool can analyze your app for common issues, but this is not guaranteed.

However, you can use this tool to integrate memory consumption into your unit test framework like NUnit or MSTest.

查看更多
▲ chillily
4楼-- · 2019-04-05 02:34

Well you can use task manager. GC apps can leak memory, and it will show there.

But...

Free tool - ".Net CLR profiler"

There is a free tool, and it's from Microsoft, and it's awesome. This is a must-use for all programs that leak references. Search MS' site.

Leaking references means you forget to set object references to null, or they never leave scope, and this is almost as likely to occur in Garbage collected languages as not - lists building up and not clearing, event handlers pointing to delegates, etc.

It's the GC equivalent of memory leaks and has the same result. This program tells you what references are taking up tons of memory - and you will know if it's supposed to be that way or not, and if not, you can go find them and fix the problem!

It even has a cool visualization of what objects allocate what memory (so you can track down mistakes). I believe there are youtubes of this if you need an explanation.

Memory Usage Visualization

Wikipedia page with download links...

NOTE: You will likely have to run your app not as a service to use this. It starts first and then runs your app. You can do this with TopShelf or by just putting the guts in a dll that runs from an EXE that implments the service integrations (service host pattern).

查看更多
混吃等死
5楼-- · 2019-04-05 02:41

I would not say that the Garbage collector is infallible. There are times when it fails unknowingly and they are not so straight forward. Memory streams are a common cause of memory leaks. You can open them in one context and they may never even get closed, even though the usage is wrapped in a using statement (the definition of a disposable object that should be cleaned up immediately after its usage falls out of scope). If you are experiencing crashes due to running out of memory, Windows does create dump files that you can sift through.

enter link description here

This is by no means fun or easy and is quite tedious but it tends to be your best bet.

Common areas that are easy to create memory leaks are anything that is using the System.Drawing dll, memory streams, and if you are doing some serious multi-threading.

查看更多
一夜七次
6楼-- · 2019-04-05 02:46

Unless you're dealing with unmanaged code, i would be so bold to say you don't have to worry about memory leaks. Any unreferenced object in managed code will be removed by the garbage collector, and the possibility in finding a memory leak within the .net framework i would say you should be considered very lucky (well, unlucky). You don't have to worry about memory leak.

However, you can still encounter ever-growing memory usage, if references to objects are never released. For example, say you keep an internal log structure, and you just keep adding entries to a log list. Then every entry still have references from the log list and therefore will never be collected.

From my experience, you can definitely use the task manager as an indicator whether your system has growing issues; if the memory usage steadily keep rising, you know you have an issue. If it grows to a point but eventually converges to a certain size, it indicates it has reached its operating threshold.

If you want a more detailed view of managed memory usage, you can download the process explorer here, developed by Microsoft. It is still quite blunt, but it gives a somewhat better statistical view than task manager.

查看更多
欢心
7楼-- · 2019-04-05 02:50

You could try the free Memoscope memory profiler

https://github.com/fremag/MemoScope.Net

I do not agree that you can trust the Task Manager to check if you have a memory leak or not. The problem with a garbage collector is that it can decide based on heuristics to keep the memory after a memory spike and do not return it to the OS. You might have a 2 GB Commit size but 90% of them can be free.

You should use VMMAP to check during the tests what type of memory your process contains. You do not only have the managed heap, but also unmanaged heap, private bytes, stacks (thread leaks), shared files and much more which need to be tracked.

VMMap has also command line interface which makes it possible to create snapshots at regular intervals which you can examine later. If you have a memory growth you can find out which type of memory is leaked which needs depending on the leak type different debugging tooling approaches.

查看更多
登录 后发表回答