Explict Memory Managment

David Semeria david at lmframework.com
Fri May 22 15:35:28 PDT 2009

On Fri, 2009-05-22 at 14:13 -0700, Brendan Eich wrote:

> Because object is a reference type, people sometimes want something like
> function copy(obj) {
>      var clone = {};
>      for (var i in obj)
>          clone[i] = obj[i];
>      return clone;
> }

Yeah, I had a lot of fun implementing a generic multi-type deep clone
myself. I think I understand the concepts, I just don't know their
proper names (mutable?).

Anyway, here is real-world example as promised:


First of all, thanks for everyone's tolerance for a chap who's on far
from solid ground here.

I really wanted to avoid referencing my own work, but it seems I don't
have much choice, so here goes:

The description below refers to a demo app. which was built using a
framework of my own creation. The app functions as a Twitter client, and
captures many of the issues I've been refering to.

The application downloads new tweets at regular intervals and adds them
to a resevoir which is implemented as a fixed-length FIFO queue. After
every update a variable number of streams are re-populated from the
resevoir using user-defined filters. For reasons which would take too
long to explain both the resevoir and streams are implemented as simple
objects, which function as hash tables.


+     +  --> [F1] -> [strm 1] 
+     +  --> [F2] -> [strm 2]
+ RES +  --> [F3] -> [strm 3]
+     +  ...
+     +  ...
+     +  --> [Fn] -> [strm n]
+     +
+     +

The streams do not contain copies of the tweets, but references to items
in the resevoir.
The size of the resevoir can be varied, but I generally use 5,000 items
The streams are stored as objects because the user can flow and reflow
them using different HTML templates
All of the structures in the framework use 1:1 references which always
point down. 

1) To make sure the new tweets appear at the top of the global resevoir
object, I need to create a new object, add the new tweets in
chronological order, then copy over the old contents of the resevoir
upto the resevoir's max length.
I then assign the new object to the global resevoir object.

2) To populate the streams, I set each stream object to {} and then
cycle through the new resevoir and add any objects (tweets) that pass
the relevant filter to the stream object.

When left to its own devices, the application (only tested under FF so
far) will generally eat up memory, reaching over 1GB if left overnight.
Whilst it's possible that there is a mistake in my code, I can't
understand where it could possibly be. I'm not creating loads of new
object defintions, just overwriting old ones.

But this is my point: before overwriting the old resevoir I could save
the GC a lot of trouble and kill it manually. The same goes for each
stream before it is overwritten.

It is also possible that the memory leaks (especially considering the
size) are coming from the DOM, since the same principle applies: the
nodes containing the old tweets are separated from their parentNode, and
the new tweets are flowed under the parentNode. Again, I could tell the
GC that those orphaned elements could be safely deleted.

I would just like to emphasize that the issue is not *why* the system is
leaking - it's that if I could kill the objects which I *know* are no
longer needed I could make the GC's job easier.

If anyone is really interested, here is a video of the system in
operation: http://lmframework.com/page.php?id=vd_twig_short_1

The video is potentially relevant because there is the additional issue
of windows (some of which have quite large objects associated with them)
being opened and hidden. When they are hidden I don't destroy them
because it seems unnecessary. This is the context in which I suggested
obj.swapOut() and obj.swapIn().

I hope this info now makes the reasons for my suggestions a bit clearer,

David Semeria

More information about the es-discuss mailing list