Dealing with Memory Leaks

1 Answer 1043 Views
General Discussions
João
Top achievements
Rank 1
Iron
Iron
Iron
João asked on 19 Jan 2022, 06:02 PM

Hey there!

I was tasked with fixing the memory leak problem of some programs, and since they have more than 100k lines combined i wanted to know something before starting :D

I want to make sure that this is the correct way of clearing/cleaning an object:

/**************************/

tmpPanel:Dispose().

tmpPanel = ?.

IF VALID-OBJECT(tmpPanel) THEN DELETE OBJECT tmpPanel NO-ERROR.

/**************************/

Am I missing something? Do I need to do anything else?

And can I do this dynamically? By sending the object in an argument and running the "Dispose" method by invoking it. Does that work as well?

And If i assign the object i want to clear/clean before doing clearing/cleaning it to another variable, should I also clear/clean such variable?

 

JP

 

1 Answer, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 20 Jan 2022, 05:31 AM

Hi, João,

I would like to let you know that our controls provide rich UI capabilities and theming mechanism which inevitably increases the memory usage. Furthermore, our components are built from the Telerik Presentation Framework which is built on top of the .NET Framework which once again, inevitably increases memory usage compared to other controls, such as the standard controls which simply wrap native objects.  Unless a certain control has a memory leak, it is eventually being disposed. Calling GC.Collect will not dispose the objects immediately, they will simply be marked for disposal and the next time the Garbage Collector passes by it will decide whether they are suitable for actual disposal. This is due to the non-deterministic behavior of the Garbage Collector. Our objects are mostly from Generation 3, which means that they will be disposed at a later state (more about garbage collection).

The questions about the memory management in .NET are usually tough because there is no guaranteed way of freeing memory deterministically. You could call GarbageColector.Collect() but that is just a polite request, not a demand and also all running threads must be suspended for garbage collection to be proceed.

Anyway DELETE OBJECT will instance the garbage collector but the garbage collector does not perform a gen#2 collection very often, it is now more important to call Dispose() on them.

As you may or may not know, the GC is split into generations - Gen #0, #1 and #2, plus the Large Object Heap.

The thought process is that you'll likely use lots of objects that will be short lived. So those should be easy and fast for the GC to get to - Gen #0 objects. So, when there is memory pressure, the first thing it does is a Gen 0 collection. Now, if that does not resolve enough pressure, then it goes back and does a Gen #1 sweep (redoing Gen #0), and then if still not enough, it does a Gen #2 cleanup (redoing Gen #1 and Gen #0). So, cleaning up long lived objects can take a while and it is very expensive since your threads may be suspended during the operation.

Our RadControls due to its complexity, will live to Generation #2. MS Controls are gen #0 because they are tiny wrappers around native Win32 components.

I hope this information helps. If you need any further assistance please don't hesitate to contact me. 

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

João
Top achievements
Rank 1
Iron
Iron
Iron
commented on 20 Jan 2022, 09:25 AM

So, let's say I'm going to create the "RadSpreedSheet" object, that usually occupies about 300MB to open. Usually on the first creation, and the delete of the same right after, a certain amount of memory will be permantly used untill I close "everything", making it faster for the future usages of such object. However instead of cleaning correctly the next times it keeps adding to the memory usage making it impossible to open/create the object without having to restart "everything".

You're telling me that disposing the object is the advised way (which is something that i already do), but you're also saying the GC only comes when "he feels like"  making it hard to control the memory usage correct?

If so, how would I resolve this problem? What would be the right way?

 

JP

Dess | Tech Support Engineer, Principal
Telerik team
commented on 24 Jan 2022, 01:23 PM

Hello, João,   

Please have in mind that in case you are showing a new RadForm instance (e.g. containing a RadSpreadsheet) every time with the ShowDialog method, the memory will be retained until the form is closed. A quote from MSDN says: "Unlike modeless forms, the Close method is not called by the .NET Framework when the user clicks the close form button of a dialog box or sets the value of the DialogResult property. Instead the form is hidden and can be shown again without creating a new instance of the dialog box. Because a form displayed as a dialog box is not closed, you must call the Dispose method of the form when the form is no longer needed by your application."

I have tested a sample project with RadSpreadsheet and its memory consumption which seems to be properly released. Please refer to the attached gif file. 

Off topic, I would like to note that this is the situation when using RadSpreadsheet in a C# Visual Studio project. However, if you are using OpenEdge and Developer Studio, I can't guarantee that the same memory management will be performed. Please note that for OpenEdge related topics the preferred places to submit a technical question are Salesforce and the Progress Community. You can log in to these websites straight from your Progress account: https://progresslink.progress.com/supportlink . Thus, the appropriate support engineers would would gladly assist you. Thank you for your understanding.
João
Top achievements
Rank 1
Iron
Iron
Iron
commented on 24 Jan 2022, 02:19 PM

Hey Dess!

Thank you for the input and it seems that it's working properly in a C# Project.

I will look into it in Openedge to see if I can catch something someone missed.

 

Have a nice one.

JP

Tags
General Discussions
Asked by
João
Top achievements
Rank 1
Iron
Iron
Iron
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Share this question
or