Is memory released on Form.close()? - c#

I am working on feedback application which have lots of form open and close operation. I noticed few changes in memory changes in my application when i start my application it takes 25 MB. With each feedback user give it increases 3 MB in memory usage. On every form i had used this.close() when it jumps from one to other or there is any close operation. What can be the possible reason of memory increases.
Do i need to call garbage collector manually, as everyone says its not good practice.
In this i am using dual monitor scenario in which application take snapshot of secondary screen after each 500 ms and shows it on primary screen. For this I am using the code shown below:
public EntryForm()
{
sc = Screen.AllScreens;
dbDms = new HondaDb(UtilityFunctions.getServerConnection());
db = new HondaDb(UtilityFunctions.getClientConnection());
bmpScreenshot = new Bitmap(sc[1].Bounds.Width,
sc[1].Bounds.Height,
PixelFormat.Format32bppArgb);
Create a graphics object from the bitmap.
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
Timer timerClientScreen = new Timer();
timerClientScreen.Interval = 500;
timerClientScreen.Enabled = false;
timerClientScreen.Start();
timerClientScreen.Tick += new EventHandler(timer_TickClient);
}
void timer_TickClient(object sender, EventArgs e)
{
// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(sc[1].Bounds.X, sc[1].Bounds.Y,
0, 0, sc[1].Bounds.Size, CopyPixelOperation.SourceCopy);
// Save the screenshot to the specified path that the user has chosen.
pictureBoxClient.Image = bmpScreenshot;
}
For closing of form on open of other I am using the code below
formOpen.show();
formClose.Close();
Suggest me how can I save memory usage.

It does, but just your UI objects. It isn't automatic for the variables you use. In an app like this, using big objects that take very little GC heap space but lots of unmanaged resources, the garbage collector doesn't typically run often enough to keep you out of trouble. You have to help and explicitly dispose the objects so you don't leave it up to the GC to take care of the job.
It may take too long for it to start running, you can build up a lot of unmanaged memory usage before it gets to run the finalizers. Potentially crashing your program with OOM, although you are still very far removed from that problem. Right now you are just running "heavy".
Add an event handler for the FormClosed event. You need to call the Dispose() method on the gfxScreenshot and bmpScreenshot objects. And surely those HondaDb objects need some kind of cleanup as well.
Do not assume that will instantly solve memory usage increments, the GC is not eager to release address space back to the operating system. Keeping it around instead with the assumption that you are likely going to have a need for it soon. The proper usage pattern is it stabilizing after a while at a reasonable number, then suddenly dropping and building back up. A saw-tooth pattern. Write a little unit test that calls creates and destroys your form object repeatedly, ensuring that it does the non-trivial jobs of taking the screenshot and accessing the dbase. Now you know with confidence that you don't have a run-away leak problem.

No, when you call Form.Close() you are just telling to close the form. the object is still there in memory and if you have a reference to it, it will be there until you have held that reference.
.NET has automatic garbage collection mechanism which collect objects that are garbage (you have no reference to them and they can not be accessed). So objects are removed from memory when they become garbage and .NET garbage collector starts it works. You can force executing garbage collector by calling GC.Collect().
More about GC

Have a look at this MSDN Thread. It's about dispoable Windows, this should release all ressource held by a an instance of a class. Then the garbage collector should do it's work.

Related

.NET Form close/dispose does not deallocate global objects

Edit: Please just take into consideration the sample I provided. There are no events being called. The code I provided is all that there is. I just want to know of global objects in a form must be manually de-allocated. It would be nice to also know why a form going out of scope doesn't get cleaned up, but that is secondary.
Closing or calling dispose on a Form does not seem to deallocate that form's global objects. I have a form that will be instantiated multiple times and after opening a number of times I am getting an OutOfMemory exception, even if all the previous forms were closed. I can get memory to free by making every object I am using disposable, but I thought in general the garbage collection took care of cleaning up objects out of scope.
Here is a simple example of a form with just a multidimensional double array:
using System;
using System.Windows.Forms;
namespace surGroupTool
{
public partial class TestForm : Form
{
double[,] testArray;
public TestForm()
{
InitializeComponent();
testArray = new double[5000, 5000];
}
}
}
When I create the form in an infinite loop it quickly runs out of memory, even if I dispose and set it to null.
while (true)
{
TestForm testForm = new TestForm();
testForm.Dispose();
testForm = null;
}
Must every object be manually disposed for a closed/disposed form?
I was unable to reproduce the issue with the given source code. This screenshot is from about 20 seconds. But I left it running while getting coffee and it was still fine. It was looping the memory pattern as shown above.
One thing I noticed is that it takes some time before the GC frees up memory. The GC only runs when your starting to get low on memory or when manually calling it with GC.Collect();. At that point a background process will start that does the actual cleaning. This garbage collection thread does not fully interrupt your programs main thread (according to the Microsoft documentation > background workstation garbage collection). So this means that it is possible to keep allocating memory even when the GC is running. At that point it is a race who's first. You in allocating enough memory to get out of bounds. or your GC with its cleanup.
Must every object be manually disposed for a closed/disposed form?
No, generally global resources do not have to be disposed. The GC will clean them up if nothing is referencing them. However if a global resources is an unmanaged resources (like a stream or a bitmap) you need to dispose it before it can be cleaned, this is the same for local unmanaged resource.
from the comments:
This happens even if each form is created by a user clicking a button...with minutes between forms being created.
I'm going to assume that this is in your real application and not with the form provided as a test sample. You are most likely leaving a reference to that form (for example via a dialog result, or open undamaged resource). If it is with the given form I cannot explain it and you might need to check if you haven't overwritten the GC settings to something very exotic, or disabled it all together.

use of forcefully calling Garbage collection method [duplicate]

The general advice is that you should not call GC.Collect from your code, but what are the exceptions to this rule?
I can only think of a few very specific cases where it may make sense to force a garbage collection.
One example that springs to mind is a service, that wakes up at intervals, performs some task, and then sleeps for a long time. In this case, it may be a good idea to force a collect to prevent the soon-to-be-idle process from holding on to more memory than needed.
Are there any other cases where it is acceptable to call GC.Collect?
If you have good reason to believe that a significant set of objects - particularly those you suspect to be in generations 1 and 2 - are now eligible for garbage collection, and that now would be an appropriate time to collect in terms of the small performance hit.
A good example of this is if you've just closed a large form. You know that all the UI controls can now be garbage collected, and a very short pause as the form is closed probably won't be noticeable to the user.
UPDATE 2.7.2018
As of .NET 4.5 - there is GCLatencyMode.LowLatency and GCLatencyMode.SustainedLowLatency. When entering and leaving either of these modes, it is recommended that you force a full GC with GC.Collect(2, GCCollectionMode.Forced).
As of .NET 4.6 - there is the GC.TryStartNoGCRegion method (used to set the read-only value GCLatencyMode.NoGCRegion). This can itself, perform a full blocking garbage collection in an attempt to free enough memory, but given we are disallowing GC for a period, I would argue it is also a good idea to perform full GC before and after.
Source: Microsoft engineer Ben Watson's: Writing High-Performance .NET Code, 2nd Ed. 2018.
See:
https://msdn.microsoft.com/en-us/library/system.runtime.gclatencymode(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/dn906204(v=vs.110).aspx
I use GC.Collect only when writing crude performance/profiler test rigs; i.e. I have two (or more) blocks of code to test - something like:
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestA(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestB(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
...
So that TestA() and TestB() run with as similar state as possible - i.e. TestB() doesn't get hammered just because TestA left it very close to the tipping point.
A classic example would be a simple console exe (a Main method sort-enough to be posted here for example), that shows the difference between looped string concatenation and StringBuilder.
If I need something precise, then this would be two completely independent tests - but often this is enough if we just want to minimize (or normalize) the GC during the tests to get a rough feel for the behaviour.
During production code? I have yet to use it ;-p
The best practise is to not force a garbage collection in most cases. (Every system I have worked on that had forced garbage collections, had underlining problems that if solved would have removed the need to forced the garbage collection, and speeded the system up greatly.)
There are a few cases when you know more about memory usage then the garbage collector does. This is unlikely to be true in a multi user application, or a service that is responding to more then one request at a time.
However in some batch type processing you do know more then the GC. E.g. consider an application that.
Is given a list of file names on the command line
Processes a single file then write the result out to a results file.
While processing the file, creates a lot of interlinked objects that can not be collected until the processing of the file have complete (e.g. a parse tree)
Does not keep match state between the files it has processed.
You may be able to make a case (after careful) testing that you should force a full garbage collection after you have process each file.
Another cases is a service that wakes up every few minutes to process some items, and does not keep any state while it’s asleep. Then forcing a full collection just before going to sleep may be worthwhile.
The only time I would consider forcing
a collection is when I know that a lot
of object had been created recently
and very few objects are currently
referenced.
I would rather have a garbage collection API when I could give it hints about this type of thing without having to force a GC my self.
See also "Rico Mariani's Performance Tidbits"
These days I consider same of the above cases would be better to use a short lived worker process to do each batch of work and let the OS do the resource recovery.
One case is when you are trying to unit test code that uses WeakReference.
In large 24/7 or 24/6 systems -- systems that react to messages, RPC requests or that poll a database or process continuously -- it is useful to have a way to identify memory leaks. For this, I tend to add a mechanism to the application to temporarily suspend any processing and then perform full garbage collection. This puts the system into a quiescent state where the memory remaining is either legitimately long lived memory (caches, configuration, &c.) or else is 'leaked' (objects that are not expected or desired to be rooted but actually are).
Having this mechanism makes it a lot easier to profile memory usage as the reports will not be clouded with noise from active processing.
To be sure you get all of the garbage, you need to perform two collections:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
As the first collection will cause any objects with finalizers to be finalized (but not actually garbage collect these objects). The second GC will garbage collect these finalized objects.
You can call GC.Collect() when you know something about the nature of the app the garbage collector doesn't.
As the author, it's often tempting to think this is likely or normal. However, the truth is the GC amounts to a pretty well-written and tested expert system, and it's rare you'll know something about the low level code paths it doesn't.
The best example I can think of where you might have some extra information is an app that cycles between idle periods and very busy periods. You want the best performance possible for the busy periods and therefore want to use the idle time to do some clean up.
However, most of the time the GC is smart enough to do this anyway.
One instance where it is almost necessary to call GC.Collect() is when automating Microsoft Office through Interop. COM objects for Office don't like to automatically release and can result in the instances of the Office product taking up very large amounts of memory. I'm not sure if this is an issue or by design. There's lots of posts about this topic around the internet so I won't go into too much detail.
When programming using Interop, every single COM object should be manually released, usually though the use of Marshal.ReleseComObject(). In addition, calling Garbage Collection manually can help "clean up" a bit. Calling the following code when you're done with Interop objects seems to help quite a bit:
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
In my personal experience, using a combination of ReleaseComObject and manually calling garbage collection greatly reduces the memory usage of Office products, specifically Excel.
As a memory fragmentation solution.
I was getting out of memory exceptions while writing a lot of data into a memory stream (reading from a network stream). The data was written in 8K chunks. After reaching 128M there was exception even though there was a lot of memory available (but it was fragmented). Calling GC.Collect() solved the issue. I was able to handle over 1G after the fix.
Have a look at this article by Rico Mariani. He gives two rules when to call GC.Collect (rule 1 is: "Don't"):
When to call GC.Collect()
I was doing some performance testing on array and list:
private static int count = 100000000;
private static List<int> GetSomeNumbers_List_int()
{
var lstNumbers = new List<int>();
for(var i = 1; i <= count; i++)
{
lstNumbers.Add(i);
}
return lstNumbers;
}
private static int[] GetSomeNumbers_Array()
{
var lstNumbers = new int[count];
for (var i = 1; i <= count; i++)
{
lstNumbers[i-1] = i + 1;
}
return lstNumbers;
}
private static int[] GetSomeNumbers_Enumerable_Range()
{
return Enumerable.Range(1, count).ToArray();
}
static void performance_100_Million()
{
var sw = new Stopwatch();
sw.Start();
var numbers1 = GetSomeNumbers_List_int();
sw.Stop();
//numbers1 = null;
//GC.Collect();
Console.WriteLine(String.Format("\"List<int>\" took {0} milliseconds", sw.ElapsedMilliseconds));
sw.Reset();
sw.Start();
var numbers2 = GetSomeNumbers_Array();
sw.Stop();
//numbers2 = null;
//GC.Collect();
Console.WriteLine(String.Format("\"int[]\" took {0} milliseconds", sw.ElapsedMilliseconds));
sw.Reset();
sw.Start();
//getting System.OutOfMemoryException in GetSomeNumbers_Enumerable_Range method
var numbers3 = GetSomeNumbers_Enumerable_Range();
sw.Stop();
//numbers3 = null;
//GC.Collect();
Console.WriteLine(String.Format("\"int[]\" Enumerable.Range took {0} milliseconds", sw.ElapsedMilliseconds));
}
and I got OutOfMemoryException in GetSomeNumbers_Enumerable_Range method the only workaround is to deallocate the memory by:
numbers = null;
GC.Collect();
You should try to avoid using GC.Collect() since its very expensive. Here is an example:
public void ClearFrame(ulong timeStamp)
{
if (RecordSet.Count <= 0) return;
if (Limit == false)
{
var seconds = (timeStamp - RecordSet[0].TimeStamp)/1000;
if (seconds <= _preFramesTime) return;
Limit = true;
do
{
RecordSet.Remove(RecordSet[0]);
} while (((timeStamp - RecordSet[0].TimeStamp) / 1000) > _preFramesTime);
}
else
{
RecordSet.Remove(RecordSet[0]);
}
GC.Collect(); // AVOID
}
TEST RESULT: CPU USAGE 12%
When you change to this:
public void ClearFrame(ulong timeStamp)
{
if (RecordSet.Count <= 0) return;
if (Limit == false)
{
var seconds = (timeStamp - RecordSet[0].TimeStamp)/1000;
if (seconds <= _preFramesTime) return;
Limit = true;
do
{
RecordSet[0].Dispose(); // Bitmap destroyed!
RecordSet.Remove(RecordSet[0]);
} while (((timeStamp - RecordSet[0].TimeStamp) / 1000) > _preFramesTime);
}
else
{
RecordSet[0].Dispose(); // Bitmap destroyed!
RecordSet.Remove(RecordSet[0]);
}
//GC.Collect();
}
TEST RESULT: CPU USAGE 2-3%
In your example, I think that calling GC.Collect isn't the issue, but rather there is a design issue.
If you are going to wake up at intervals, (set times) then your program should be crafted for a single execution (perform the task once) and then terminate. Then, you set the program up as a scheduled task to run at the scheduled intervals.
This way, you don't have to concern yourself with calling GC.Collect, (which you should rarely if ever, have to do).
That being said, Rico Mariani has a great blog post on this subject, which can be found here:
http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx
One useful place to call GC.Collect() is in a unit test when you want to verify that you are not creating a memory leak (e. g. if you are doing something with WeakReferences or ConditionalWeakTable, dynamically generated code, etc).
For example, I have a few tests like:
WeakReference w = CodeThatShouldNotMemoryLeak();
Assert.IsTrue(w.IsAlive);
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.IsFalse(w.IsAlive);
It could be argued that using WeakReferences is a problem in and of itself, but it seems that if you are creating a system that relies on such behavior then calling GC.Collect() is a good way to verify such code.
There are some situations where it is better safe than sorry.
Here is one situation.
It is possible to author an unmanaged DLL in C# using IL rewrites (because there are situations where this is necessary).
Now suppose, for example, the DLL creates an array of bytes at the class level - because many of the exported functions need access to such. What happens when the DLL is unloaded? Is the garbage collector automatically called at that point? I don't know, but being an unmanaged DLL it is entirely possible the GC isn't called. And it would be a big problem if it wasn't called. When the DLL is unloaded so too would be the garbage collector - so who is going to be responsible for collecting any possible garbage and how would they do it? Better to employ C#'s garbage collector. Have a cleanup function (available to the DLL client) where the class level variables are set to null and the garbage collector called.
Better safe than sorry.
The short answer is: never!
using(var stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
techObject.Last().Image = Image.FromStream(stream);
bitmap.Dispose();
// Without this code, I had an OutOfMemory exception.
GC.Collect();
GC.WaitForPendingFinalizers();
//
}
Another reason is when you have a SerialPort opened on a USB COM port, and then the USB device is unplugged. Because the SerialPort was opened, the resource holds a reference to the previously connected port in the system's registry. The system's registry will then contain stale data, so the list of available ports will be wrong. Therefore the port must be closed.
Calling SerialPort.Close() on the port calls Dispose() on the object, but it remains in memory until garbage collection actually runs, causing the registry to remain stale until the garbage collector decides to release the resource.
From https://stackoverflow.com/a/58810699/8685342:
try
{
if (port != null)
port.Close(); //this will throw an exception if the port was unplugged
}
catch (Exception ex) //of type 'System.IO.IOException'
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
}
port = null;
If you are creating a lot of new System.Drawing.Bitmap objects, the Garbage Collector doesn't clear them. Eventually GDI+ will think you are running out of memory and will throw a "The parameter is not valid" exception. Calling GC.Collect() every so often (not too often!) seems to resolve this issue.
i am still pretty unsure about this.
I am working since 7 years on an Application Server. Our bigger installations take use of 24 GB Ram. Its hightly Multithreaded, and ALL calls for GC.Collect() ran into really terrible performance issues.
Many third party Components used GC.Collect() when they thought it was clever to do this right now.
So a simple bunch of Excel-Reports blocked the App Server for all threads several times a minute.
We had to refactor all the 3rd Party Components in order to remove the GC.Collect() calls, and all worked fine after doing this.
But i am running Servers on Win32 as well, and here i started to take heavy use of GC.Collect() after getting a OutOfMemoryException.
But i am also pretty unsure about this, because i often noticed, when i get a OOM on 32 Bit, and i retry to run the same Operation again, without calling GC.Collect(), it just worked fine.
One thing i wonder is the OOM Exception itself...
If i would have written the .Net Framework, and i can't alloc a memory block, i would use GC.Collect(), defrag memory (??), try again, and if i still cant find a free memory block, then i would throw the OOM-Exception.
Or at least make this behavior as configurable option, due the drawbacks of the performance issue with GC.Collect.
Now i have lots of code like this in my app to "solve" the problem:
public static TResult ExecuteOOMAware<T1, T2, TResult>(Func<T1,T2 ,TResult> func, T1 a1, T2 a2)
{
int oomCounter = 0;
int maxOOMRetries = 10;
do
{
try
{
return func(a1, a2);
}
catch (OutOfMemoryException)
{
oomCounter++;
if (maxOOMRetries > 10)
{
throw;
}
else
{
Log.Info("OutOfMemory-Exception caught, Trying to fix. Counter: " + oomCounter.ToString());
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(oomCounter * 10));
GC.Collect();
}
}
} while (oomCounter < maxOOMRetries);
// never gets hitted.
return default(TResult);
}
(Note that the Thread.Sleep() behavior is a really App apecific behavior, because we are running a ORM Caching Service, and the service takes some time to release all the cached objects, if RAM exceeds some predefined values. so it waits a few seconds the first time, and has increased waiting time each occurence of OOM.)
one good reason for calling GC is on small ARM computers with little memory, like the Raspberry PI (running with mono).
If unallocated memory fragments use too much of the system RAM, then the Linux OS can get unstable.
I have an application where I have to call GC every second (!) to get rid of memory overflow problems.
Another good solution is to dispose objects when they are no longer needed. Unfortunately this is not so easy in many cases.
This isn't that relevant to the question, but for XSLT transforms in .NET (XSLCompiledTranform) then you might have no choice. Another candidate is the MSHTML control.
If you are using a version of .net less than 4.5, manual collection may be inevitable (especially if you are dealing with many 'large objects').
this link describes why:
https://blogs.msdn.microsoft.com/dotnet/2011/10/03/large-object-heap-improvements-in-net-4-5/
Since there are Small object heap(SOH) and Large object heap(LOH)
We can call GC.Collect() to clear de-reference object in SOP, and move lived object to next generation.
In .net4.5, we can also compact LOH by using largeobjectheapcompactionmode

Memory Leak in C# WPF

I need to reduce the memory leak in c# WPF after disposing all the used objects. But I couldn't reduce the memory consumption completely by using the following code snippet.
Here is my code:
string str;
Uri uri;
private void Button_Click(object sender, RoutedEventArgs e) // "Load" Button
{
if(img.Source!=null)
Unload();
str = "F://Photos//Parthi//IMG_20141128_172826244.jpg"; // File Size: 0.643 MB
uri = new Uri(str);
img.Source = new BitmapImage(uri);
}
private void Button_Click_1(object sender, RoutedEventArgs e) //"Unload Button"
{
Unload();
}
private void Unload()
{
Bitmap bmp = GetBitmap(img.Source as BitmapSource);
bmp.Dispose();
bmp = null;
img.Source = null;
str = string.Empty;
uri = null;
}
private Bitmap GetBitmap(BitmapSource source)
{
Bitmap bmp = new Bitmap(source.PixelWidth, source.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
source.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
bmp.UnlockBits(data);
data = null;
source = null;
return bmp;
}
After Running the sample, While checking it in Task manager, the following memory consumption reading has produced,
Before "Load" Button is clicked : 10.0 MB
After "Load" Button is clicked : 47.8 MB
After "Unload" Button is clicked : 26.0 MB
After Unloading, I need to reduce the memory closely to 10.0 MB. So please help me regarding this.
Thanks in Advance.
Using the .net platform does not have control over the memory as if it works in c / c ++
The garbage collector operates very complex policies and the fact that you see down the memory to 26 but 10 is normal.
The .net reserves a space to recharge faster data and guarantee a free space in main memory without having to require continuous OS.
What I've noticed is perfectly normal.
It 'a question that in the past I personally subjected to a Microsoft MVP during a course
View this:
http://msdn.microsoft.com/en-us/library/ee787088%28v=vs.110%29.aspx
and this: Best Practice for Forcing Garbage Collection in C#
First of all, do not use Task Manager to view your memory usage, because it only shows the memory that the windows process allocates. There are plenty of much better tools out there and even the Performance Monitor, which comes on Windows, will give you a better idea of your application performance and any memory leaks. You may start it by running perfmon.exe.
In this sample application, GC does not become aggressive with collections until heap reaches approximately 85MB. And why would I want it to? It's not a lot of memory and it works very well as a caching solution, if I decide to use the same objects again.
So, I suggest taking a look at that tool. It gives a nice overview of what's going on and it's free.
Second of all, just because you called a .Dispose() to release those resources, does not mean that memory is released right away. You're basically making it eligible for the garbage collection and when GC gets to it, it'll take care of it.
The default garbage collection behavior for a WPF application is Concurrent(<4.0)/Background(4.0=<) Workstation GC. It runs on a special thread and most of the time tries to run concurrently to the rest of the application (I say most of the time, because once in a while it'll extremely briefly suspend other threads, so that it may complete its cleanup). It doesn't wait until you're out of memory, but at the same time, it does collection only when it doesn't affect the performance greatly -- sort of a balanced trade-off.
Another factor to consider is that you have a 0.643 MB jpeg file and once you count in BitmapImage, it's a bit more... well, anything above 85,000 bytes is considered to be a large object and thus, it is placed into generation 2, which contains the large object heap. Generation 2 garbage collection is expensive and is done infrequently. However, if you're running .NET 4.5.1, and I'm not sure if you are, you may force a compaction:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collection();
As with .Dipose(), this is not going happen right away, as it's an expensive process and it'll take a little longer than the generation 1 less-than-a-millisecond sweep. And honestly, you probably wouldn't even benefit from it, since I doubt that you would have a high fragmentation in the LOH with that application. I just mentioned it so that you're aware of that option if you ever need it.
So, why am I giving you a brief lesson on the default GC behavior of a WPF application (and most of .NET applications for that matter)? Well, it's important to understand the behavior of GC and acknowledge its existence. Unlike a C++ application, where you're granted a lot of control and freedom over your memory allocation, a .NET application utilizes a GC. The trade-off is that the memory is freed when it's freed by the GC. There may even be times when it frees it prematurely, from your point of view, and that's when you would explicitly keep an object alive by calling GC.KeepAlive(..). A lot of embedded systems do not make use of a GC and if you want very precise control over your memory, I suggest that you do not either.
If you want to be aware of how memory is being handled in a .NET application, I strongly recommend educating yourself on the inner workings of the garbage collector. What I've told you about is an incredibly brief snapshot of the default behavior and there is a lot more to it. There are a few modes, which provide different behaviors.
try to manage the usage of your variables. you can do something like this :
private void Button_Click(object sender, RoutedEventArgs e)
{
img.Source = new BitmapImage(new Uri(#"F://Photos//Parthi//IMG_20141128_172826244.jpg"));
}
if 'str' and 'uri' is not necessary needed by the whole class you can just add it directly it to your object. Or if you really need to store it and reuse your data that really has a huge amount of size you can just store it on Physical file on a temp file to prevent memory leakage; instead of storing it to memory you can store it on physical storage.
hope it helps
Your Unload method calls GetBitmap, but GetBitmap returns a new object every time, so as far as I can tell, you're never actually going to dispose of img.Source properly

Is correct to use GC.Collect(); GC.WaitForPendingFinalizers();?

I've started to review some code in a project and found something like this:
GC.Collect();
GC.WaitForPendingFinalizers();
Those lines usually appear on methods that are conceived to destruct the object under the rationale of increase efficiency. I've made this remarks:
To call garbage collection explicitly on the destruction of every object decreases performance because doing so does not take into account if it is absolutely necessary for CLR performance.
Calling those instructions in that order causes every object to be destroyed only if other objects are being finalized. Therefore, an object that could be destroyed independently has to wait for another object's destruction without a real necessity.
It can generate a deadlock (see: this question)
Are 1, 2 and 3 true? Can you give some reference supporting your answers?
Although I'm almost sure about my remarks, I need to be clear in my arguments in order to explain to my team why is this a problem. That's the reason I'm asking for confirmation and reference.
The short answer is: take it out. That code will almost never improve performance, or long-term memory use.
All your points are true. (It can generate a deadlock; that does not mean it always will.) Calling GC.Collect() will collect the memory of all GC generations. This does two things.
It collects across all generations every time - instead of what the GC will do by default, which is to only collect a generation when it is full. Typical use will see Gen0 collecting (roughly) ten times as often than Gen1, which in turn collects (roughly) ten times as often as Gen2. This code will collect all generations every time. Gen0 collection is typically sub-100ms; Gen2 can be much longer.
It promotes non-collectable objects to the next generation. That is, every time you force a collection and you still have a reference to some object, that object will be promoted to the subsequent generation. Typically this will happen relatively rarely, but code such as the below will force this far more often:
void SomeMethod()
{
object o1 = new Object();
object o2 = new Object();
o1.ToString();
GC.Collect(); // this forces o2 into Gen1, because it's still referenced
o2.ToString();
}
Without a GC.Collect(), both of these items will be collected at the next opportunity. With the collection as writte, o2 will end up in Gen1 - which means an automated Gen0 collection won't release that memory.
It's also worth noting an even bigger horror: in DEBUG mode, the GC functions differently and won't reclaim any variable that is still in scope (even if it's not used later in the current method). So in DEBUG mode, the code above wouldn't even collect o1 when calling GC.Collect, and so both o1 and o2 will be promoted. This could lead to some very erratic and unexpected memory usage when debugging code. (Articles such as this highlight this behaviour.)
EDIT: Having just tested this behaviour, some real irony: if you have a method something like this:
void CleanUp(Thing someObject)
{
someObject.TidyUp();
someObject = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
... then it will explicitly NOT release the memory of someObject, even in RELEASE mode: it'll promote it into the next GC generation.
There is a point one can make that is very easy to understand: Having GC run automatically cleans up many objects per run (say, 10000). Calling it after every destruction cleans up about one object per run.
Because GC has high overhead (needs to stop and start threads, needs to scan all objects alive) batching calls is highly preferable.
Also, what good could come out of cleaning up after every object? How could this be more efficient than batching?
Your point number 3 is technically correct, but can only happen if someone locks during a finaliser.
Even without this sort of call, locking inside a finaliser is even worse than what you have here.
There are a handful of times when calling GC.Collect() really does help performance.
So far I've done so 2, maybe 3 times in my career. (Or maybe about 5 or 6 times if you include those where I did it, measured the results, and then took it out again - and this is something you should always measure after doing).
In cases where you're churning through hundreds or thousands of megs of memory in a short period of time, and then switching over to much less intensive use of memory for a long period of time, it can be a massive or even vital improvement to explicitly collect. Is that what's happening here?
Anywhere else, they're at best going to make it slower and use more memory.
See my other answer here:
To GC.Collect or not?
two things can happen when you call GC.Collect() yourself: you end up spending more time doing collections (because the normal background collections will still happen in addition to your manual GC.Collect()) and you'll hang on to the memory longer (because you forced some things into a higher order generation that didn't need to go there). In other words, using GC.Collect() yourself is almost always a bad idea.
About the only time you ever want to call GC.Collect() yourself is when you have specific information about your program that is hard for the Garbage Collector to know. The canonical example is a long-running program with distinct busy and light load cycles. You may want to force a collection near the end of a period of light load, ahead of a busy cycle, to make sure resources are as free as possible for the busy cycle. But even here, you might find you do better by re-thinking how your app is built (ie, would a scheduled task work better?).
We have run into similar problems to #Grzenio however we are working with much larger 2-dimensional arrays, in the order of 1000x1000 to 3000x3000, this is in a webservice.
Adding more memory isn't always the right answer, you have to understand your code and the use case. Without GC collecting we require 16-32gb of memory (depending on customer size). Without it we would require 32-64gb of memory and even then there are no guarantees the system won't suffer. The .NET garbage collector is not perfect.
Our webservice has an in-memory cache in the order of 5-50 million string (~80-140 characters per key/value pair depending on configuration), in addition with each client request we would construct 2 matrices one of double, one of boolean which were then passed to another service to do the work. For a 1000x1000 "matrix" (2-dimensional array) this is ~25mb, per request. The boolean would say which elements we need (based on our cache). Each cache entry represents one "cell" in the "matrix".
The cache performance dramatically degrades when the server has > 80% memory utilization due to paging.
What we found is that unless we explicitly GC the .net garbage collector would never 'cleanup' the transitory variables until we were in the 90-95% range by which point the cache performance had drastically degraded.
Since the down-stream process often took a long duration (3-900 seconds) the performance hit of a GC collection was neglible (3-10 seconds per collect). We initiated this collect after we had already returned the response to the client.
Ultimately we made the GC parameters configurable, also with .net 4.6 there are further options. Here is the .net 4.5 code we used.
if (sinceLastGC.Minutes > Service.g_GCMinutes)
{
Service.g_LastGCTime = DateTime.Now;
var sw = Stopwatch.StartNew();
long memBefore = System.GC.GetTotalMemory(false);
context.Response.Flush();
context.ApplicationInstance.CompleteRequest();
System.GC.Collect( Service.g_GCGeneration, Service.g_GCForced ? System.GCCollectionMode.Forced : System.GCCollectionMode.Optimized);
System.GC.WaitForPendingFinalizers();
long memAfter = System.GC.GetTotalMemory(true);
var elapsed = sw.ElapsedMilliseconds;
Log.Info(string.Format("GC starts with {0} bytes, ends with {1} bytes, GC time {2} (ms)", memBefore, memAfter, elapsed));
}
After rewriting for use with .net 4.6 we split the garbage colleciton into 2 steps - a simple collect and a compacting collect.
public static RunGC(GCParameters param = null)
{
lock (GCLock)
{
var theParams = param ?? GCParams;
var sw = Stopwatch.StartNew();
var timestamp = DateTime.Now;
long memBefore = GC.GetTotalMemory(false);
GC.Collect(theParams.Generation, theParams.Mode, theParams.Blocking, theParams.Compacting);
GC.WaitForPendingFinalizers();
//GC.Collect(); // may need to collect dead objects created by the finalizers
var elapsed = sw.ElapsedMilliseconds;
long memAfter = GC.GetTotalMemory(true);
Log.Info($"GC starts with {memBefore} bytes, ends with {memAfter} bytes, GC time {elapsed} (ms)");
}
}
// https://msdn.microsoft.com/en-us/library/system.runtime.gcsettings.largeobjectheapcompactionmode.aspx
public static RunCompactingGC()
{
lock (CompactingGCLock)
{
var sw = Stopwatch.StartNew();
var timestamp = DateTime.Now;
long memBefore = GC.GetTotalMemory(false);
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
var elapsed = sw.ElapsedMilliseconds;
long memAfter = GC.GetTotalMemory(true);
Log.Info($"Compacting GC starts with {memBefore} bytes, ends with {memAfter} bytes, GC time {elapsed} (ms)");
}
}
Hope this helps someone else as we spent a lot of time researching this.
[Edit] Following up on this, we have found some additional problems with the large matrices. we have started encountering heavy memory pressure and the application suddenly being unable to allocate the arrays, even if the process/server has plenty of memory (24gb free). Upon deeper investigation we discovered that the process had standby memory that was almost 100% of the "in use memory" (24gb in use, 24gb standby, 1gb free). When the "free" memory hit 0 the application would pause for 10+ seconds while standby was reallocated as free and then it could start responding to requests.
Based on our research this appears to be due to fragmentation of the large object heap.
To address this concern we are taking 2 approaches:
We are going to change to jagged array vs multi-dimensional arrays. This will reduce the amount of continuous memory required, and ideally keep more of these arrays out of the Large Object Heap.
We are going to implement the arrays using the ArrayPool class.
I've used this just once: to clean up server-side cache of Crystal Report documents. See my response in Crystal Reports Exception: The maximum report processing jobs limit configured by your system administrator has been reached
The WaitForPendingFinalizers was particularly helpful for me, as sometimes the objects were not being cleaned up properly. Considering the relatively slow performance of the report in a web page - any minor GC delay was negligible, and the improvement in memory management gave an overall happier server for me.

Memory leak happens when using thread inside another thread

Below sample code has memory leak. If I comment out the two lines inside RefreshTimer_Elapsed, then the memory leak is gone. Does anybody know what's wrong? Thanks for help.
static void RefreshTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Thread innerThread = new Thread(delegate() { });
innerThread.Start();
}
static void Main(string[] args)
{
System.Timers.Timer RefreshTimer = new System.Timers.Timer();
RefreshTimer.Interval = 5000;
RefreshTimer.Elapsed += new System.Timers.ElapsedEventHandler(RefreshTimer_Elapsed);
RefreshTimer.Start();
for (; ; )
{ }
}
Are you sure theres a memory leak? Or do you notice that your memory just grows?
Until the garbage collector cleans up all the threads you create, memory will grow, but its not leaking, the garbage collector knows that this is dead memory.
The only way memory "leaks" in a managed enviroment like .NET or java is when you have objects being referenced that are never used or needed. Thats not the case here. You're just creating a bunch of threads and forget about them immediately. As soon as they're no longer referenced by RefreshTimer_Elapsed and the thread stops running then there are no more references and they are free to be cleaned.
You won't see the memory drop until the garbage collector is ready to do a cleanup. You can try and force this but its not generally recommended for performance reasons.
What you see might be just resources not yet reclaimed by the Garbage collector because there is no memory pressure.
Also you have a busy for loop in your Main routine, you probably want a Thread.Sleep statement there for testing, unless this is somehow part of this test...
To force a garbage collection just for your testing only you could replace your for loop with:
while(true)
{
Thread.Sleep(5000);
GC.Collect();
GC.WaitForPendingFinalizers();
}
In general when examining 'memory leaks' or resource problems in managed code I would recommend using a profiler (i.e. Redgate ANTS) and take a closer look at the allocations over time.
I think it's because you keep creating new threads.
The Timer object needs to be disposed!
It appears you are creating new items as there is a recursive call of the code and there may be some kind of loop developing at runtime causing untidy filling of memory with multiple copies of objects as every called item does not fully complete.
RefreshTimer_Elapsed makes a new thread every interval. What kind of work is the anonymous method doing? Is it completing? Every thread you make will get 1MB of virtual memory allocated via Windows.
If you threads never finish, then every interval, you will consume another 1MB of memory.

Categories

Resources