Tuesday, January 4, 2011

Managing Your Memory

When you build applications with REAL Studio, you don't have to think about managing memory to the extent that you would had you created your application using many other development tools. For the most part, the REAL Studio framework handles memory management for you.

For example, if in the Open event of a window or webpage you have created a picture and stored it in a property called MyPic:

MyPic = new picture(100, 100, 32)

Then in some event you set a local variable ("x" let's say) to MyPic and then set MyPic to nil:

x = MyPic
MyPic = nil

When you set x equal to MyPic, what you really are doing is making x point to the same picture object as MyPic. Neither MyPic nor x store the picture. The picture is stored in memory by the REAL Studio framework. What you are doing is pointing the MyPic property at the picture. This is a subtle but important distinction. So when you set MyPic to nil, you are not removing the picture from memory, you are indicating that MyPic now points to nothing.

So when does the picture get removed from memory? In this case, when x also becomes nil. It might become nil by you setting it to nil or, since it's a local variable, when the event ends x will automatically be made nil. When that happens, since there is nothing else referencing the picture, the REAL Studio framework will remove the picture itself from memory.

Most modern frameworks handle memory via one of two methods. They either use
Reference Counting or Garbage Collection. REAL Studio uses Reference Counting. That means that each time something references an object, REAL Studio increments a counter by one and when something stops referencing that object, it decrements that counter by one. Once the counter gets to zero, the framework automatically removes it from memory.

The other form of memory management, Garbage Collection, works a bit differently. Instead of a count of how many things reference an object, this system checks to see if there are any references to objects. It does this on a schedule and then removes the object from memory if nothing references it.

Each method has its own strengths and weaknesses. The weakness of Garbage Collection is that the garbage collector can kick in at an inconvenient moment and affect the performance of your application. There are usually ways for the developer to tell the garbage collector to run so that they have some control over it but it's not 100%. The benefit of Garbage Collection is that it will clear every object from memory, therefore there is no chance for memory leaks.

What is a memory leak? A memory leak is when objects should be cleared from memory but are not. With Reference Counting, you can, by accident, create a memory leak. However, Reference Counting provides for consistent performance. And as long as you are diligent, you won't have memory leaks. It requires a little more effort on your part but you don't have to worry about having uneven performance.

I wanted to write about this after reading an article about performance issues with Android apps. One of Google's Android engineers said that, among other things, Garbage Collection was an issue that affects performance and battery life. Android applications are written in Java and Java uses Garbage Collection.

Personally, I think Referencing Counting is the best solution as it provides even performance and is generally more efficient than Garbage Collection. By "efficient" I mean that it takes less CPU cycles to get the job done. However, like religion and politics, you will never get everyone to agree.

Since REAL Studio uses Reference Counting, just make sure when you store a reference to an object in a property that you add code that will clear (set to nil) that property when the object is no longer needed. If the property is a property or a window or webpage and you are going to need the object until the window or webpage is closed, there is no need to worry about it because when the window or page closes, the properties are all cleared and the object they reference will be cleared as well. Something to keep in mind, if the property is a property of a class, the property will go away when the instance of the class does; but if it's a property of a module or the app class, it will stay around until you specifically set it to nil.

Fortunately, managing memory is mostly handled for you by REAL Studio. As your application gets more complex you will have to take a little more responsibility. But at least your application won't suddenly panic when the garbage man shows up unexpectedly.


Thomas Tempelmann said...

I suggest also having a look at this RBWiki article: http://www.declaresub.com/wiki/index.php/Circular_References

It shows how to avoid leaks from circular references, along with code to find them.

Chris said...

Do you have a link for the Android article Geoff?

Geoff Perlman said...

@ Chris -Here's the article. Right in the beginning they talk about getting rid of Garbage Collection to improve animation performance:


Kiko Lobo said...

Geoff, Is there a way to check how many references are left in an object like we can on Objective-C?

Geoff Perlman said...

@ Kiko - No, not currently. However, it's not a bad idea. We could add something to the debugger that would show this information so that if you suspected you have a memory leak, you could see how much progress you are making towards fixing it.

BTW, what does the name "Kiko" mean? I ask because as a child we had a cat named Kiko but I have no idea where the name came from.

Unknown said...

Isn't that article kind of ironic considering most Realbasic app ( especially the web ones ) crash because of leaking memory in realbasic framework? I dare anyone to run a stand alone WE app more then 2 hours without it running out of memory.

Geoff Perlman said...

There was a memory leak but it has been fixed. As I mentioned in the article, the bigger the app is, the more diligent one must be. The REAL Studio framework is VERY big.

Sean Beach said...

I'm also in favor of a debugger feature to show object references.

On a side note, I don't really like having to cast my weakref with the class name everytime I want to use it. My solution has been computed properties:

Private myRef as WeakRef

c as MyClass Get:
return myClass(myRef.value)
c as MyClass Set:
myRef = new WeakRef(value)

Geoff Perlman said...

@ Sean - Have you created a feature request for showing object references in the debugger? What's the case number?