I am trying to write a class that wraps a buffer allocated with Marshal.AllocHGlobal. I implemented the IDisposable interface, and added a finalizer that should release the memory when I don't need it anymore (when the object goes out of scope).
When I test the class, the GC does not call the finalizer or the Dispose method of my classes, even though they are out of scope. As a result, I get an OutOfMemoryException.
Why does the GC not call the finalizer, and why does the memory not get freed?
Here is a short example that illustrates the problem. In the sample, there is nothing written to the console (except Unhandled Exception: OutOfMemoryException.)
class Buffer : IDisposable
{
public IntPtr buf { get; set; }
public Buffer()
{
buf = Marshal.AllocHGlobal(4 * 1024 * 1024);
}
~Buffer()
{
Console.WriteLine("Finalizer called");
Dispose(false);
}
public void Dispose()
{
Console.WriteLine("Dispose called");
Dispose(true);
GC.SuppressFinalize(this);
}
internal virtual void Dispose(bool disposing)
{
if (buf != IntPtr.Zero)
{
Console.WriteLine("Releasing memory");
Marshal.FreeHGlobal(buf);
buf = IntPtr.Zero;
}
}
}
class Program
{
static void Main(string[] args)
{
while(true)
{
Buffer b = new Buffer();
Thread.Sleep(20);
}
}
}
EDIT: Here is the .NET performance counters for my test program when it crashes:
You need to tell the garbage collector that your very small managed objects with a single IntPtr field have a high cost in terms of unmanaged memory. Currently, the garbage collector is blissfully unaware of the fact that each small managed object uses a large amount of unmanaged memory and has no reason to perform any collection.
You can use the GC.AddMemoryPressure when you allocate the unmanaged memory and GC.RemoveMemoryPressure when you free the unmanaged memory.
Garbage collection occurs when one of the following conditions is true:
The system has low physical memory.
The memory that is used by allocated objects on the managed heap
surpasses an acceptable threshold. This threshold is continuously
adjusted as the process runs.
The GC.Collect method is called. In almost all cases, you do not
have to call this method, because the garbage collector runs
continuously. This method is primarily used for unique situations
and testing.
Also the garbage collector tracks memory only on the managed heap, so for this program, the only condition can trigger GC is the first one.
I compiled the program, if the target CPU is x86, it will through out of memory exception when the private bytes of the process reaches about 2G. When I run the program, I noticed the private bytes increase quickly, but the working set increase very slowly, and also the system physical memory usage increase very slowly.
As private bytes and working set, this post explains:
Private Bytes refer to the amount of memory that the process executable has asked for - not necessarily the amount it is actually using. They are "private" because they (usually) exclude memory-mapped files (i.e. shared DLLs). But - here's the catch - they don't necessarily exclude memory allocated by those files. There is no way to tell whether a change in private bytes was due to the executable itself, or due to a linked library. Private bytes are also not exclusively physical memory; they can be paged to disk or in the standby page list (i.e. no longer in use, but not paged yet either).
Working Set refers to the total physical memory (RAM) used by the process. However, unlike private bytes, this also includes memory-mapped files and various other resources, so it's an even less accurate measurement than the private bytes. This is the same value that gets reported in Task Manager's "Mem Usage" and has been the source of endless amounts of confusion in recent years. Memory in the Working Set is "physical" in the sense that it can be addressed without a page fault; however, the standby page list is also still physically in memory but not reported in the Working Set, and this is why you might see the "Mem Usage" suddenly drop when you minimize an application.
Marshal.AllocHGlobal just increases the private bytes, but the working set is still small, it doesn't trigger GC either.
Please refer this: Fundamentals of Garbage Collection
IDisposable is declarative, The dispose method is only called when Garbage collection actually happens.
Yoy can force garbage collection to happen , for this You need to call
GC.Collect
http://msdn.microsoft.com/en-us/library/xe0c2357(v=vs.110).aspx
I would also recommend using preformance counters to see you app memory consumtion, and see if GC is already called. see here how to do it http://msdn.microsoft.com/en-us/library/x2tyfybc(v=vs.110).aspx
I have an application that saves/caches many objects in a static field. When there are a lot of objects saved during the lifetime of the application, there is out of memory exception being thrown because the cache grows so large.
Is there any class or object that informs me that the memory is running out and there will be an outofmemoryexception throwing soon so that I can know that I need to free up some memory by removing some of these cached objects? I'm looking for a sign that there is memory pressure in the application so that I can take precautionary action during application runtime before the memory exception is thrown.
I also have an application that uses as much ram as it possibly can. You have a couple of options here depending on your specific scenario (all have drawbacks).
One of the simplest is to preallocate a circular buffer of classes (or bytes) that you are caching to consume all ram up front. This usually is not preferred because consuming all the RAM on a box when you don't need to is just plain Rude.
Another way to handle large caches (or keep from throwing out of memory exceptions) is to first check that the memory I need exists before allocation. This has the drawback of needing to serialize memory allocations. Otherwise the time between the available RAM check and the allocation you may run out of RAM.
Here is a sample of the best way I have found to do this in .NET:
//Wait for enough memory
var temp = new System.Diagnostics.PerformanceCounter("Memory", "Available MBytes");
long freeMemory = Convert.ToInt64(temp.NextValue()) * (long)1000000;
long neededMemory = (long)bytesToAllocate;
int attempts=1200; //two minutes
while (freeMemory < neededMemory)
{
//Signal that memory needs to be freed
Console.WriteLine("Waiting for enough free memory:. Free Memory:" + freeMemory + " Needed Memory(MB):" + neededMemory);
System.Threading.Thread.Sleep(100);
freeMemory = Convert.ToInt64(temp.NextValue()) * (long)1000000;
--attempts;
if (0 == attempts)
throw new OutOfMemoryException("Could not get enough free memory. File:" + Path.GetFileName(wavFileURL));
}
//Try and allocate the memory we need.
Furthermore once I am inside the while loop I signal that some memory needs to be freed (depending on your application). NOTE: I tried to simplify the code by using a Sleep statement but ultimately you would want some type of non polling operation if possible.
I am not sure about the specifics of your application but if you are multithreaded, or run many different executables then it may be better to serialize this memory check when allocated memory to the cache. If that is the case I use a Semaphore to make sure that only one thread and/or process can allocate RAM as needed. Similar to this:
Semaphore namedSemaphore = new Semaphore(1, 1, "MemoryAllocationSemaphore"); //named semaphores are cross process
if (bytesToAllocate > 2000000) //if we need less than 2MB then dont bother locking.
{
if (!namedSemaphore.WaitOne((int)TimeSpan.FromMinutes(15).TotalMilliseconds))
{
throw new TimeoutException("Waited over 15 minutes for aquiring memory allocation semaphore");
}
}
Then a little later on call this:
namedSemaphore.Release();
in a finally block to release the semaphore.
Another option is to use a multiple reader single writer lock. To have multiple threads pulling data from the cache (such as the ReaderWriterLock class). This has the advantage that while you are writing to can check memory pressure and cleanup then add more to the cache, yet still have multiple threads processing data. The drawback is of course the bottle neck of getting data into the cache comes from a single fixed point.
If you have so much data cached that you're running out of memory that indicates something seriously wrong with your caching approach. Even as a 32-bit process, you have a 2 GB address space.
You should consider using a limited cache where the user can set a preferred cache size and you automatically remove objects when this size is reached. You can implement certain caching strategies to pick which objects to remove from the cache: oldest objects or the least frequently used objects or a combination of these.
You can also try mapping some of your cache to disk and only keep the most frequently used objects in memory. When an object is needed that's not in memory, you can de-serialize it from disk and put it back in memory. If an object is then unused for a period of time, you can swap it to disk.
I'm noticing a lot of byte[] getting stuck in memory when profiling my program. I did some digging and found the majority of the instances created in some manner like this:
public byte[] CreateBytes(byte[] bytes)
{
using (var start = new MemoryStream())
{
using (var memStr = new MemoryStream(bytes))
{
//do stuff
return start.ToArray();
}
}
}
The returned byte[] is then passed to other methods and is used in creating another MemoryStream from within another using block:
using (var uncompressedStream = new MemoryStream(uncompressedData))
{
using (var compressedStream = new MemoryStream())
{
//Do some compression
}
}
myObject.Bytes = uncompressedData;
uncompressedData = null;
return myObject;
(uncompressedData is the value returned from CreateBytes()).
My question is, when does the byte[] get cleaned up? Do I specifically need to set it to null, and if so, where? After the second using block I no longer need it, but if I simply put uncompressedData = null; I'm not sure that's going to reclaim the memory.
I would've thought that the using statement in CreateBytes(byte[] bytes) would've disposed of the bytes, but since it's returning a reference does that postpone and/or forego the disposal?
EDIT: I added another line of code. Since I'm storing the uncompressedBtyes in another object, setting uncompressedData to null is pointless and the byte[] will live as long as myObject (or until myObject.Bytes is set to null), correct?
The byte[] gets cleaned up when two conditions are both satisfied:
There are no references to that memory block
The garbage collector decides to collect that memory block
The GC runs at non-deterministic times based on a variety of factors.
The byte array, just like any other managed object in memory, is eligible for garbage collection as soon as it is no longer accessible from any root reference. You can trust the GC to know when that's happened, and to intelligently schedule times to actually do the clean up of eligible objects. Try not to worry about when an object that's eligible for cleanup is actually cleaned up, chances are the GC knows better than you.
In addition to Erics answer:
When you are sure you do not more need that byte[], assign to it null.
This will not guarantee that memory will be reclaimed now, neither that it will be reclimed after, this is just a way to help GC to identify it like a subject for collection.
The using statement really has nothing to do with the byte array you are returning.
The MemoryStream is disposable, and disposal of that object is what the using statement is managing (note that disposal is not the same as garbage collection, but is typically a precursor thereto).
When you call ToArray(), you are creating something new that is not disposable; once it is out of scope, it will be cleaned up by the garbage collector at an indeterminate time (this is typically a well optimized process).
I have an application that is used in image processing, and I find myself typically allocating arrays in the 4000x4000 ushort size, as well as the occasional float and the like. Currently, the .NET framework tends to crash in this app apparently randomly, almost always with an out of memory error. 32mb is not a huge declaration, but if .NET is fragmenting memory, then it's very possible that such large continuous allocations aren't behaving as expected.
Is there a way to tell the garbage collector to be more aggressive, or to defrag memory (if that's the problem)? I realize that there's the GC.Collect and GC.WaitForPendingFinalizers calls, and I've sprinkled them pretty liberally through my code, but I'm still getting the errors. It may be because I'm calling dll routines that use native code a lot, but I'm not sure. I've gone over that C++ code, and make sure that any memory I declare I delete, but still I get these C# crashes, so I'm pretty sure it's not there. I wonder if the C++ calls could be interfering with the GC, making it leave behind memory because it once interacted with a native call-- is that possible? If so, can I turn that functionality off?
EDIT: Here is some very specific code that will cause the crash. According to this SO question, I do not need to be disposing of the BitmapSource objects here. Here is the naive version, no GC.Collects in it. It generally crashes on iteration 4 to 10 of the undo procedure. This code replaces the constructor in a blank WPF project, since I'm using WPF. I do the wackiness with the bitmapsource because of the limitations I explained in my answer to #dthorpe below as well as the requirements listed in this SO question.
public partial class Window1 : Window {
public Window1() {
InitializeComponent();
//Attempts to create an OOM crash
//to do so, mimic minute croppings of an 'image' (ushort array), and then undoing the crops
int theRows = 4000, currRows;
int theColumns = 4000, currCols;
int theMaxChange = 30;
int i;
List<ushort[]> theList = new List<ushort[]>();//the list of images in the undo/redo stack
byte[] displayBuffer = null;//the buffer used as a bitmap source
BitmapSource theSource = null;
for (i = 0; i < theMaxChange; i++) {
currRows = theRows - i;
currCols = theColumns - i;
theList.Add(new ushort[(theRows - i) * (theColumns - i)]);
displayBuffer = new byte[theList[i].Length];
theSource = BitmapSource.Create(currCols, currRows,
96, 96, PixelFormats.Gray8, null, displayBuffer,
(currCols * PixelFormats.Gray8.BitsPerPixel + 7) / 8);
System.Console.WriteLine("Got to change " + i.ToString());
System.Threading.Thread.Sleep(100);
}
//should get here. If not, then theMaxChange is too large.
//Now, go back up the undo stack.
for (i = theMaxChange - 1; i >= 0; i--) {
displayBuffer = new byte[theList[i].Length];
theSource = BitmapSource.Create((theColumns - i), (theRows - i),
96, 96, PixelFormats.Gray8, null, displayBuffer,
((theColumns - i) * PixelFormats.Gray8.BitsPerPixel + 7) / 8);
System.Console.WriteLine("Got to undo change " + i.ToString());
System.Threading.Thread.Sleep(100);
}
}
}
Now, if I'm explicit in calling the garbage collector, I have to wrap the entire code in an outer loop to cause the OOM crash. For me, this tends to happen around x = 50 or so:
public partial class Window1 : Window {
public Window1() {
InitializeComponent();
//Attempts to create an OOM crash
//to do so, mimic minute croppings of an 'image' (ushort array), and then undoing the crops
for (int x = 0; x < 1000; x++){
int theRows = 4000, currRows;
int theColumns = 4000, currCols;
int theMaxChange = 30;
int i;
List<ushort[]> theList = new List<ushort[]>();//the list of images in the undo/redo stack
byte[] displayBuffer = null;//the buffer used as a bitmap source
BitmapSource theSource = null;
for (i = 0; i < theMaxChange; i++) {
currRows = theRows - i;
currCols = theColumns - i;
theList.Add(new ushort[(theRows - i) * (theColumns - i)]);
displayBuffer = new byte[theList[i].Length];
theSource = BitmapSource.Create(currCols, currRows,
96, 96, PixelFormats.Gray8, null, displayBuffer,
(currCols * PixelFormats.Gray8.BitsPerPixel + 7) / 8);
}
//should get here. If not, then theMaxChange is too large.
//Now, go back up the undo stack.
for (i = theMaxChange - 1; i >= 0; i--) {
displayBuffer = new byte[theList[i].Length];
theSource = BitmapSource.Create((theColumns - i), (theRows - i),
96, 96, PixelFormats.Gray8, null, displayBuffer,
((theColumns - i) * PixelFormats.Gray8.BitsPerPixel + 7) / 8);
GC.WaitForPendingFinalizers();//force gc to collect, because we're in scenario 2, lots of large random changes
GC.Collect();
}
System.Console.WriteLine("Got to changelist " + x.ToString());
System.Threading.Thread.Sleep(100);
}
}
}
If I'm mishandling memory in either scenario, if there's something I should spot with a profiler, let me know. That's a pretty simple routine there.
Unfortunately, it looks like #Kevin's answer is right-- this is a bug in .NET and how .NET handles objects larger than 85k. This situation strikes me as exceedingly strange; could Powerpoint be rewritten in .NET with this kind of limitation, or any of the other Office suite applications? 85k does not seem to me to be a whole lot of space, and I'd also think that any program that uses so-called 'large' allocations frequently would become unstable within a matter of days to weeks when using .NET.
EDIT: It looks like Kevin is right, this is a limitation of .NET's GC. For those who don't want to follow the entire thread, .NET has four GC heaps: gen0, gen1, gen2, and LOH (Large Object Heap). Everything that's 85k or smaller goes on one of the first three heaps, depending on creation time (moved from gen0 to gen1 to gen2, etc). Objects larger than 85k get placed on the LOH. The LOH is never compacted, so eventually, allocations of the type I'm doing will eventually cause an OOM error as objects get scattered about that memory space. We've found that moving to .NET 4.0 does help the problem somewhat, delaying the exception, but not preventing it. To be honest, this feels a bit like the 640k barrier-- 85k ought to be enough for any user application (to paraphrase this video of a discussion of the GC in .NET). For the record, Java does not exhibit this behavior with its GC.
Here are some articles detailing problems with the Large Object Heap. It sounds like what you might be running into.
http://connect.microsoft.com/VisualStudio/feedback/details/521147/large-object-heap-fragmentation-causes-outofmemoryexception
Dangers of the large object heap:
http://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/
Here is a link on how to collect data on the Large Object Heap (LOH):
http://msdn.microsoft.com/en-us/magazine/cc534993.aspx
According to this, it seems there is no way to compact the LOH. I can't find anything newer that explicitly says how to do it, and so it seems that it hasn't changed in the 2.0 runtime:
http://blogs.msdn.com/maoni/archive/2006/04/18/large-object-heap.aspx
The simple way of handling the issue is to make small objects if at all possible. Your other option to is to create only a few large objects and reuse them over and over. Not an idea situation, but it might be better than re-writing the object structure. Since you did say that the created objects (arrays) are of different sizes, it might be difficult, but it could keep the application from crashing.
Start by narrowing down where the problem lies. If you have a native memory leak, poking the GC is not going to do anything for you.
Run up perfmon and look at the .NET heap size and Private Bytes counters. If the heap size remains fairly constant but private bytes is growing then you've got a native code issue and you'll need to break out the C++ tools to debug it.
Assuming the problem is with the .NET heap you should run a profiler against the code like Redgate's Ant profiler or JetBrain's DotTrace. This will tell you which objects are taking up the space and not being collected quickly. You can also use WinDbg with SOS for this but it's a fiddly interface (powerful though).
Once you've found the offending items it should be more obvious how to deal with them. Some of the sort of things that cause problems are static fields referencing objects, event handlers not being unregistered, objects living long enough to get into Gen2 but then dying shortly after, etc etc. Without a profile of the memory heap you won't be able to pinpoint the answer.
Whatever you do though, "liberally sprinkling" GC.Collect calls is almost always the wrong way to try and solve the problem.
There is an outside chance that switching to the server version of the GC would improve things (just a property in the config file) - the default workstation version is geared towards keeping a UI responsive so will effectively give up with large, long running colections.
Use Process Explorer (from Sysinternals) to see what the Large Object Heap for your application is. Your best bet is going to be making your arrays smaller but having more of them. If you can avoid allocating your objects on the LOH then you won't get the OutOfMemoryExceptions and you won't have to call GC.Collect manually either.
The LOH doesn't get compacted and only allocates new objects at the end of it, meaning that you can run out of space quite quickly.
If you're allocating a large amount of memory in an unmanaged library (i.e. memory that the GC isn't aware of), then you can make the GC aware of it with the GC.AddMemoryPressure method.
Of course this depends somewhat on what the unmanaged code is doing. You haven't specifically stated that it's allocating memory, but I get the impression that it is. If so, then this is exactly what that method was designed for. Then again, if the unmanaged library is allocating a lot of memory then it's also possible that it's fragmenting the memory, which is completely beyond the GC's control even with AddMemoryPressure. Hopefully that's not the case; if it is, you'll probably have to refactor the library or change the way in which it's used.
P.S. Don't forget to call GC.RemoveMemoryPressure when you finally free the unmanaged memory.
(P.P.S. Some of the other answers are probably right, this is a lot more likely to simply be a memory leak in your code; especially if it's image processing, I'd wager that you're not correctly disposing of your IDIsposable instances. But just in case those answers don't lead you anywhere, this is another route you could take.)
Just an aside: The .NET garbage collector performs a "quick" GC when a function returns to its caller. This will dispose the local vars declared in the function.
If you structure your code such that you have one large function that allocates large blocks over and over in a loop, assigning each new block to the same local var, the GC may not kick in to reclaim the unreferenced blocks for some time.
If on the other hand, you structure your code such that you have an outer function with a loop that calls an inner function, and the memory is allocated and assigned to a local var in that inner function, the GC should kick in immediately when the inner function returns to the caller and reclaim the large memory block that was just allocated, because it's a local var in a function that is returning.
Avoid the temptation to mess with GC.Collect explicitly.
Apart from handling the allocations in a more GC-friendly way (e.g. reusing arrays etc.), there's a new option now: you can manually cause compaction of the LOH.
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
This will cause a LOH compaction the next time a gen-2 collection happens (either on its own, or by your explicit call of GC.Collect).
Do note that not compacting the LOH is usually a good idea - it's just that your scenario is a decent enough case for allowing for manual compaction. The LOH is usually used for huge, long-living objects - like pre-allocated buffers that are reused over time etc.
If your .NET version doesn't support this yet, you can also try to allocate in sizes of powers of two, rather than allocating precisely the amount of memory you need. This is what a lot of native allocators do to ensure memory fragmentation doesn't get impossibly stupid (it basically puts an upper limit on the maximum heap fragmentation). It's annoying, but if you can limit the code that handles this to a small portion of your code, it's a decent workaround.
Do note that you still have to make sure it's actually possible to compact the heap - any pinned memory will prevent compaction in the heap it lives in.
Another useful option is to use paging - never allocating more than, say, 64 kiB of contiguous space on the heap; this means you'll avoid using the LOH entirely. It's not too hard to manage this in a simple "array-wrapper" in your case. The key is to maintain a good balance between performance requirements and reasonable abstraction.
And of course, as a last resort, you can always use unsafe code. This gives you a lot of flexibility in handling memory allocations (though it's a bit more painful than using e.g. C++) - including allowing you to explicitly allocate unmanaged memory, do your work with that and release the memory manually. Again, this only makes sense if you can isolate this code to a small portion of your total codebase - and make sure you've got a safe managed wrapper for the memory, including the appropriate finalizer (to maintain some decent level of memory safety). It's not too hard in C#, though if you find yourself doing this too often, it might be a good idea to use C++/CLI for those parts of the code, and call them from your C# code.
Have you tested for memory leaks? I've been using .NET Memory Profiler with quite a bit of success on a project that had a number of very subtle and annoyingly persistent (pun intended) memory leaks.
Just as a sanity check, ensure that you're calling Dispose on any objects that implement IDisposable.
You could implement your own array class which breaks the memory into non-contiguious blocks. Say, have a 64 by 64 array of [64,64] ushort arrays which are allocated and deallocated seperately. Then just map to the right one. Location 66,66 would be at location [2,2] in the array at [1,1].
Then, you should be able to dodge the Large Object Heap.
The problem is most likely due to the number of these large objects you have in memory. Fragmentation would be a more likely issue if they are variable sizes (while it could still be an issue.) You stated in the comments that you are storing an undo stack in memory for the image files. If you move this to Disk you would save yourself tons of application memory space.
Also moving the undo to disk should not cause too much of a negative impact on performance because it's not something you will be using all of the time. (If it does become a bottle neck you can always create a hybrid disk/memory cache system.)
Extended...
If you are truly concerned about the possible impact of performance caused by storing undo data on the file system, you may consider that the virtual memory system has a good chance of paging this data to your virtual page file anyway. If you create your own page file/swap space for these undo files, you will have the advantage of being able to control when and where the disk I/O is called. Don't forget, even though we all wish our computers had infinite resources they are very limited.
1.5GB (useable application memory space) / 32MB (large memory request size) ~= 46
you can use this method:
public static void FlushMemory()
{
Process prs = Process.GetCurrentProcess();
prs.MinWorkingSet = (IntPtr)(300000);
}
three way to use this method.
1 - after dispose managed object such as class ,....
2 - create timer with such 2000 intervals.
3 - create thread to call this method.
i suggest to you use this method in thread or timer.
The best way to do it is like this article show, it is in spanish, but you sure understand the code.
http://www.nerdcoder.com/c-net-forzar-liberacion-de-memoria-de-nuestras-aplicaciones/
Here the code in case link get brock
using System.Runtime.InteropServices;
....
public class anyname
{
....
[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);
public static void alzheimer()
{
GC.Collect();
GC.WaitForPendingFinalizers();
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
}
....
you call alzheimer() to clean/release memory.
The GC doesn't take into account the unmanaged heap. If you are creating lots of objects that are merely wrappers in C# to larger unmanaged memory then your memory is being devoured but the GC can't make rational decisions based on this as it only see the managed heap.
You end up in a situation where the GC doesn't think you are short of memory because most of the things on your gen 1 heap are 8 byte references where in actual fact they are like icebergs at sea. Most of the memory is below!
You can make use of these GC calls:
System::GC::AddMemoryPressure(sizeOfField);
System::GC::RemoveMemoryPressure(sizeOfField);
These methods allow the GC to see the unmanaged memory (if you provide it the right figures).