What is being garbage collected?

I’m developing on windows 10. I’ve noticed more garbage collection then I like. It’s not effecting performance yet but I want to figure out what is causing the collection. Is there any tools that can tell me what is being garbage collected?

You can turn on diagnostics to take a memory snapshot while running. It’s not as good as DotTrace but it’ll at least get you object counts and some indication of where to look. You can compare snapshots to see what’s changing.

The wizard in Debug -> Performance Profiler will work if you don’t quite know what you’re doing. It isn’t always trustworthy though. (you have to uncheck everything except wizard and then select allocation in the popup) msdn instructions

Linq, foreach, and Tasks create heaps of low impact garbage.

And for the sake of completeness, although you sound like you’ve already thought of that, every object you allocate using ‘new’. Use pooling for those if you cannot avoid allocating objects.

It’s probably the mouse and keyboard code.

Conversion of numerical text into numbers which is a c# thing itself can be a culprit too, though that’s solvable.

These are the primary things that create garbage in mg internally. Unfortunately you can’t do anything about the keyboard mouse as i think this is coming from the librarys mg depends on.

Anytime you call new you actually are creating garbage however its the collections of garbage that causes stutters.

// very bad
var t = new T(0);
for(int i = 0; i  < 100; i++)
{
t = new T(i);
t.Draw();
}

// much more preferable.
var t = new T();
for(int i = 0; i  < 100; i++)
{
t.x = i;
t.Draw();
}

I’m right now in the same boat, trying to detect GCs. It is sad, because some time ago CLR Profiler did a great job when trying to discover GC allocations, but it is no longer maintained, and for some reason VS2015 and 17 are not providing that information.

Maybe we should open a suggestion to UserVoice and vote for it.

Also in .NET Core 2 you’re supposed to be able to change the Garbage Collector. Maybe it could be possible to write a custom garbage collector that logs all the instances being collected just for debug purposes, plug that GC to detect them, and use the standard one in runtime. Of course, MG should run with NET Core 2.

I went ahead and created the uservoice request. Please upvote if you’re interested in better garbage detection :slight_smile:

https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/33690382-information-about-garbage-collected-items

I usually have a gc counter up with my fps counter.

You can actually manually track memory on code blocks with the System.Gc class. I just wrote out a class that will watch just a specific area to demonstrate.

// this class uses the system namespace.

    public static class GarbageCollectionWatcher
    {
        private static int numberOfPasses = 0;
        private static long start = 0;
        private static long end = 0;
        private static long difference = 0;
        private static long totalMemoryAllocatedInTheBlock = 0;
        private static long totalMemoryLostInTheBlock = 0;

        public static void Start()
        {
            start = System.GC.GetTotalMemory(false);
        }
        public static void Stop()
        {
            end = System.GC.GetTotalMemory(false);
            numberOfPasses++;
            difference = end - start;
            if (difference < 0)
            {
                // a collect between start end which resulted in lost memory occured.
                totalMemoryLostInTheBlock += difference;
            }
            if (difference > 0)
            {
                // something has generated garbage here. 
                // that however isn't neccessarily a bad thing.
                // unless it is continuous beyond start up.
                totalMemoryAllocatedInTheBlock += difference;
            }
        }
        /// <summary>
        /// This is to tell you how much total memory the code between start and stop creates.
        /// If the area is constantly generating garbage then its probably bad..
        /// </summary>
        public static long GetTotalMemoryAllocatedInTheBlock()
        {
            return totalMemoryAllocatedInTheBlock;
        }
        /// <summary>
        /// When we see memory lost in this block this value increases.
        /// This is typically a bad sign that the block triggered a collect.
        /// If this is increasing non stop its a very bad sign.
        /// </summary>
        public static long GetTotalMemoryLostInTheBlock()
        {
            return totalMemoryLostInTheBlock;
        }
    }

so like to use this.

            GarbageCollectionWatcher.Start();
            string s = "make some garbage " + gameTime.ElapsedGameTime.Milliseconds;
            GarbageCollectionWatcher.Stop();

            Gv.spriteBatch.DrawString(font, GarbageCollectionWatcher.GetTotalMemoryAllocatedInTheBlock().ToString() , new Vector2(50, 200), Color.Yellow);
            Gv.spriteBatch.DrawString(font, GarbageCollectionWatcher.GetTotalMemoryLostInTheBlock().ToString() , new Vector2(50, 220), Color.Red);

thanks, I also print the number of GC run but I hadn’t thought of using the GC data this way. :slight_smile:

However it’s sad such a tool is not integrated already in VS. I mean, with the “memory snapshot” in the diagnostic tools they have a very accurate image of the memory currently being used, down to the address of each instance. Printing all the collected instances would be as easy as finding every instance present in a previous snapshot and not present in the current one, and display. The data is there, they just have present it in a different way. (if only we could write the memory snapshot into disk we could try to decode it and print differences between two snapshots, but afaik that can’t be done either)

It’d really make the task of discovering this kind of issues a breeze.

I put my Gc related classes up on github they are basically stand alone.

It’s basically in all the pictures i post, i use them all the time.

The MgStringBuilder class i use for everything text related. (as it really doesn’t make garbage)

Including the FrameRate class which itself is garbage free and gives some gc information as well. I also added a new class in there that word wraps text to a rectangle. This one doesn’t draw it, it just inserts newlines as needed, It’s kinda the opposite of measurestring(). Basically its like pre-formating a string for monogame drawstring its actually super cool.

I normally keep a static class with a static setup() draw() and update() were these classes are setup updated and drawn. Then i just have the three calls in game one. Basically i test in open gl and as soon as i see garbage i track it down.

1 Like