3

I'm currently trying to do memory analysis on a C# project I am working on to determine if there any leaks since this application needs to have as close to 100% up-time as possible. I started using the Ants Memory Profiler version 7.4, and noticed that my unmanaged memory was growing continuously over time even though my managed memory was not.

After more experimenting, I tried doing a similar analysis on a program that does nothing but block on a Console.ReadLine() instruction. I ran the analysis and noticed the same thing happening. My unmanaged heap was slowly growing. In fact, it actually only seemed to grow as the garbage collector was being called (by the snapshot functionality). Now why would calling garbage collect repeatedly lead to an un-endable increase in unmanaged memory? Was it something to do with ANTS?

I would like to use some other tool, preferably something like windbg or SOS to determine what it sees my unmanaged memory usage is. It is not important right now for me to know what is in it -- although this may help for debugging in the long run. I'm simply trying to determine the unmanaged memory usage of an application currently running. I would like to see if this is really an issue with ants or a misunderstanding by me of how the environment works. Having some sort of .net, visual studio, or windows tool to give me accurate information about my process would help me with this.

trincot
  • 317,000
  • 35
  • 244
  • 286
user2245290
  • 31
  • 1
  • 3
  • 1
    Is your code 100% C#, or is there some C++/CLI or unmanaged C++? – dario_ramos Apr 04 '13 at 14:31
  • 1
    is it a windows form project? WindowsForm uses unmanaged Window API for drawing object – Draykos Apr 04 '13 at 14:32
  • Sorry, I completely left out that vital information. I am not explicitly using any unmanaged code. The code has some threads and uses some .net socket objects. It also runs as a console application -- there is no winform or wpf component in it. Lastly, even when I mocked out all .net networking objects and got rid of my threads -- i still saw this. Also keep in mind that for a simple application with one line that just blocks on ReadLine(), I saw this behavior as well. – user2245290 Apr 04 '13 at 14:35
  • 1
    The most important aspect of what I was trying to get across was the growth of unmanaged memory in a simple one line program. Console.ReadLine(). At the start of the blocking, my unmanaged memory usage -- according to ants memory profiler -- is 2.834 MB. After 42 snapshots, my unmanaged memory is up to 3.483 MB. Can anyone explain this? – user2245290 Apr 04 '13 at 15:13

3 Answers3

1

AQTime from SmartBear does a pretty good job giving you memory analysis on both managed and unmanaged code. A lot of my work is in the managed and unmananged boundary and I've used it multiple times to find memory leaks.

If you're working with large blocks of unmanaged memory, be sure to call GC.AddMemoryPressure and GC.RemoveMemoryPressure to help the GC along.

plinth
  • 48,267
  • 11
  • 78
  • 120
  • I'm not explicitly working with unmanaged memory. All the unmanaged memory that is being used is being done on my behalf due to whatever .net managed objects I happen to be using at the time. But thanks, I'll take a look at AQTime. – user2245290 Apr 04 '13 at 14:49
0

System.GC.GetTotalMemory(bool) might be what you are looking for. Here is the annotated example from the link:

using System;
namespace GCCollectIntExample
{
    class MyGCCollectClass
    {
        private const long maxGarbage = 1000;
        static void Main()
        {
            MyGCCollectClass myGCCol = new MyGCCollectClass();

            // Determine the maximum number of generations the system 
        // garbage collector currently supports.
            Console.WriteLine("The highest generation is {0}", GC.MaxGeneration);

            myGCCol.MakeSomeGarbage();

            // Determine which generation myGCCol object is stored in.
            Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));

            // Determine the best available approximation of the number  
            // of bytes currently allocated in managed memory.
            Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));

            // Perform a collection of generation 0 only.
            GC.Collect(0);

            // Determine which generation myGCCol object is stored in.
            Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));

            Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));

            // Perform a collection of all generations up to and including 2.
            GC.Collect(2);

            // Determine which generation myGCCol object is stored in.
            Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));
            Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));
            Console.Read();
        }

        void MakeSomeGarbage()
        {
            Version vt;

            for(int i = 0; i < maxGarbage; i++)
            {
                // Create objects and release them to fill up memory 
                // with unused objects.
               vt = new Version();
            }
        }
    }
}
Cole Tobin
  • 9,206
  • 15
  • 49
  • 74
  • @Robert yes I know. But I answer like this: Answer. Add detail. Add example. Clarify. Clarify. Be grammar nazi. Fix other's answers. Get rep. Feel like a Skeet-wanna-be. – Cole Tobin Apr 04 '13 at 14:38
  • Post link only answer, risk downvotes that never get removed because person doesn't come back to recheck your answer, or answer getting deleted. Your choice I guess. – Robert Harvey Apr 04 '13 at 14:39
  • 1
    This has to do with managed memory, my problem has to do with analyzing unmanaged memory. I mentioned above that my managed memory was not growing over time. – user2245290 Apr 04 '13 at 14:40
  • You can't determine unmanaged usage as the heap is just a linked list (in essence) without any link to what program uses it. You can get a rough estimate by determining the value task manager displays – Cole Tobin Apr 04 '13 at 14:43
  • @Robert turning the example at the link into a codeblock here isn't easy (when you are using the mobile site) – Cole Tobin Apr 04 '13 at 14:45
  • Cole, on a related note. Ants was giving me a summary of my unmanaged heap usage. If i look at the value the task manager displays over time, and keep track of these values -- would that provide accurate enough information to be able to provide any meaningful comparing/contrasting with what ants gave me? I want to see, if in reality, the garbage collector is increasing my memory footprint. – user2245290 Apr 04 '13 at 14:46
  • 2
    I can imagine. Someone once told me that tablets are content consumption devices, not content production devices, and I became enlightened. – Robert Harvey Apr 04 '13 at 14:47
  • A program can provide you with the size if its programmed that way. In the case of an IDE, it most likely works by intercepting all calls to `malloc` and friends and increasing (or decreasing) an internal value based on the parameter and if it succeeded. For example, I call `malloc(0x1000)` at the beginning of the program. The debugger intercepts it and adds `0x1000` to a counter if the call worked. – Cole Tobin Apr 04 '13 at 14:51
0

use garbagge collector profiler. in case there are more objects on bucket 2 and 3 than 1 then you are not managing your unmanaged resources correctly

RollRoll
  • 8,133
  • 20
  • 76
  • 135
  • If my managed memory isn't growing in size, and ants confirms that new objects aren't being created in my managed memory, then is this method viable for determining anything about my unmanaged heap? – user2245290 Apr 04 '13 at 14:47