I built a quick program that needed to loop through an enormous log file (a couple of million records) and find various bits and pieces from inside. Because the volume of data was so huge, I have been curious to watch my Windows Task Manager performance tab and see how much CPU and memory is being used.
After the program successfully gets my results, the CPU usage goes right down, obviously. But after watching my memory usage slowly go up to several gigabytes during execution, it stays the same.
I have tried to call GC.Collect() at the end of my function, tried setting things to null, tried to run the program in Release mode (I heard that GC.Collect() might not work as I want it to in debug mode).
The memory usage goes right down if I close the program, but I can't figure out why I can't clean my app up during the apps lifetime. At the end of the day this is a throwaway app, but I'm just curious to know what I'm missing i.e. what is holding on to all this memory.
Thoughts?
When an object is no longer used, the garbage collector reclaims the underlying memory and reuses it for future object allocation. This means there is no explicit deletion and no memory is given back to the operating system.
The reclaimed memory space can then be used for future object allocations within that program. Garbage collection ensures that a program does not exceed its memory quota or reach a point that it can no longer function.
Garbage collection makes Java memory efficient because it removes the unreferenced objects from heap memory and makes free space for new objects. The Java Virtual Machine has eight types of garbage collectors.
Drawbacks of garbage collection in Java Garbage collectors bring some runtime overhead that is out of the programmer's control. This could lead to performance problems for large applications that scale large numbers of threads or processors, or sockets that consume a large amount of memory.
Calling GC.Collect() is only a request to collect garbage, it's not an order, so the CLR may choose to ignore the request if it sees fit.
For example, if there's a lot of garbage that would cause a noticable delay whilst collecting, but there's still free memory to service subsequent allocations, then the GC may opt to ignore your request.
It's normal for many memory allocators (with or w/o garbage collection) to "hoard" the memory they've freed, rather than give it back to the OS, because in many situations the memory just freed will be requested again and it's faster to keep it in the process rather than keep giving it back and asking the OS for it again and again (giving it back &c also requires extra effort due to page alignment issues and the like).
In a one-shot app, as you mention, that's not a problem. When I have a long-running app that has what I know will be a transient requirement for a lot of memory, one approach I use is to spawn a sub-process to perform the memory-hungry stuff, since when that process ends the OS will claw back the memory. It's easier on Unix systems (just fork) but not too bad on Windows, either, when warranted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With