I play with a garbage collector in C # (or rather CLR?), Trying to better understand memory management in C #.
I made a small trial program that reads three large files into the byte[] buffer. I would like to see if
- I really need anything to work efficiently with memory
- this has any effect when setting
byte[] to null after the end of the current iteration - and finally, if that helps, if you force the garbage collection through
GC.Collect()
Disclaimer: I measured memory consumption using the Windows Task Manager and rounded it. I tried several times, but overall it remained about the same.
Here is my simple sample program:
static void Main(string[] args) { Loop(); } private static void Loop() { var list = new List<string> { @"C:\Users\Public\Music\Sample Music\Amanda.wma",
For each test, I just changed the contents of the foreach . Then I started the program, at each Console.ReadLine() I stopped and checked the memory usage in the process in the Windows task manager. I took notes about the memory used, and then continued with the return program (I know about breakpoints;)). Right after the loop ended, I wrote GC.CollectionCount(1) to the console to see how often the GC jumped, if at all.
results
Test 1: foreach ( ... ) { byte[] buffer = File.ReadAllBytes(pathname); Console.WriteLine ... }
Result (memory used):
before loop: 9.000 K 1. iteration: 13.000 K 2. iteration: 19.000 K 3. iteration: 25.000 K after loop: 25.000 K GC.CollectionCount(1): 2
Test 2:
foreach ( ... ) { byte[] buffer = File.ReadAllBytes(pathname); buffer = null; Console.WriteLine ... }
Result (memory used):
before loop: 9.000 K 1. iteration: 13.000 K 2. iteration: 14.000 K 3. iteration: 15.000 K after loop: 15.000 K GC.CollectionCount(1): 2
Test 3:
foreach ( ... ) { byte[] buffer = File.ReadAllBytes(pathname); buffer = null; GC.Collect(); Console.WriteLine ... }
Result (memory used):
before loop: 9.000 K 1. iteration: 8.500 K 2. iteration: 8.600 K 3. iteration: 8.600 K after loop: 8.600 K GC.CollectionCount(1): 3
What? I do not understand:
- In test 1, memory increases with each iteration. Therefore, I think the memory is NOT freed at the end of the loop. But the GC still says it collected 2 times (
GC.CollectionCount ). Why so? - In test 2, this clearly helps set
buffer to null . The memory is lower than in Test 2. But why is GC.CollectionCount output 2, not 3? And why is memory usage not as low as in Test 3? - Test 3 uses the least memory. I would say that this is so because 1. the memory reference is deleted (
buffer set to null ), and therefore, when the garbage collector is called via GC.Collect() , it can free up memory. Seems pretty clear.
If someone with more experience can shed some light on some of the points above, it would really help me. Pretty interesting topic imho.