My code is using many Dictionaries and I’m having issues freeing memory from all of them. When I investigate using what I learned in this answer I see that the GenericEqualityComparer is there, and I suspect that is what is keeping this memory in use.
Can anyone confirm this, or tell me how I can free up this memory?
Code
Console.WriteLine("{0,10}: Start Point", GC.GetTotalMemory(true));
List<string> t1 = new List<string>();
Console.WriteLine("{0,10}: <------- Create List", GC.GetTotalMemory(true));
t1 = null;
Console.WriteLine("{0,10}: <------- null List", GC.GetTotalMemory(true));
GC.Collect();
Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
Dictionary<string, string> t2 = new Dictionary<string, string>();
Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
t2 = null;
Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));
GC.Collect();
Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
Dictionary<string, string> t3 = new Dictionary<string, string>();
Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
t3 = null;
Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));
GC.Collect();
Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
Dictionary<string, string> t4 = new Dictionary<string, string>();
Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
t4 = null;
Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));
GC.Collect();
Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
Dictionary<string, string> t5 = new Dictionary<string, string>();
Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
t5 = null;
Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));
GC.Collect();
Console.WriteLine("{0,10}: After GC.Collect", GC.GetTotalMemory(true));
Dictionary<string, string> t6 = new Dictionary<string, string>();
Console.WriteLine("{0,10}: <------- Create Dict", GC.GetTotalMemory(true));
GC.KeepAlive(t6);
t6 = null;
Console.WriteLine("{0,10}: <------- null Dict", GC.GetTotalMemory(true));
GC.Collect();
Console.WriteLine("{0,10}: <------- End.", GC.GetTotalMemory(true));
Note: I have two versions of this code. One edit with GC.Collect as was suggested here on SO, but that affords no benefit.
Output without GC Collection
95884: Start Point
97872: <------- Create List
97888: <------- null List
97952: <------- Create Dict
97968: <------- null Dict
98032: <------- Create Dict
98048: <------- null Dict
98112: <------- Create Dict
98128: <------- null Dict
98192: <------- Create Dict
98208: <------- null Dict
98272: <------- Create Dict
98288: <------- null Dict
Output With GC collection (per suggestion)
96004: Start Point
97992: <------- Create List
98008: <------- null List
98024: After GC.Collect
98088: <------- Create Dict
98104: <------- null Dict
98120: After GC.Collect
98184: <------- Create Dict
98200: <------- null Dict
98216: After GC.Collect
98280: <------- Create Dict
98296: <------- null Dict
98312: After GC.Collect
98376: <------- Create Dict
98392: <------- null Dict
98408: After GC.Collect
98472: <------- Create Dict
98488: <------- null Dict
98504: <------- End.
Output in Release mode (per suggestion)
96028: Start Point
98016: <------- Create List
98032: <------- null List
98048: After GC.Collect
98112: <------- Create Dict
98128: <------- null Dict
98144: After GC.Collect
98208: <------- Create Dict
98224: <------- null Dict
98240: After GC.Collect
98304: <------- Create Dict
98320: <------- null Dict
98336: After GC.Collect
98400: <------- Create Dict
98416: <------- null Dict
98432: After GC.Collect
98496: <------- Create Dict
98512: <------- null Dict
98528: <------- End.
Output in Release mode without GC Collect (per suggestion)
96028: Start Point
98016: <------- Create List
98032: <------- null List
98096: <------- Create Dict
98112: <------- null Dict
98176: <------- Create Dict
98192: <------- null Dict
98256: <------- Create Dict
98272: <------- null Dict
98336: <------- Create Dict
98352: <------- null Dict
98416: <------- Create Dict
98432: <------- null Dict
98448: <------- End.
In debug mode GC does not collect objects in your current method scope, because references to them still exist. Try build it for release, run without debugging and check results.
Code that prints true in debug mode but false in release:
Edit from OP: Debug mode did make the memory usage increase artificially. When I ran the stand alone app, I got this output. Thank you, and I’m accepting this answer.