JavaScript garbage collection

Created 30th November, 2007 13:20 (UTC), last edited 30th November, 2007 14:16 (UTC)

Jonathan Dodds describes closures in JavaScript¹ [1Via Reg.] and briefly discusses the reasons for why people blame closures for JavaScript memory leaks.

He explains that it's because the Windows JavaScript script engine uses a different garbage collector for COM objects which isn't very effective. This points the way to a problem that I'm likely to run into on the next stage of Mahlee™ development.

Mahlee™ uses the same JavaScript engine as Internet Explorer, the Windows scripting hosts and the “classic” ASP host to implement all of the JavaScript stuff. This is why it only took me a couple of weekends to implement the first version of it (well, the Boost.Thread library helped too). But this first version has a problem.

In order to make the implementation simpler I decided not to bother trying to track the underlying data structures that provide the inter-thread communication. Basically once you send a message the parameters and the return value remain until the host exits² [2For reasons too boring to go into this isn't a problem for the web site Mahlee™ host.]. Clearly this is a nasty memory leak, but one that seemed appropriate for an alpha version of a very experimental idea.

The strategy I was planning on using to solve it has involved changing the use of the JSON strings the futures pass return values to other threads with in such a way that I would always get matching create and destroy actions even when futures were passed on. In the first versions of Mahlee you could pick up a future and duplicate it into other threads without the Mahlee runtime knowing about it. Now the future is bound by Mahlee in such a way that the reference count is reliable.

If what Jonathan explains about the COM garbage collector in JavaScript is correct then this still isn't going to work properly as the COM objects whose destructors I'd be relying on to feed through to my lower level reference count won't themselves get garbage collected.

What it amounts to is that I will need to change the instrumentation strategy that I use to check my low level garbage collection to ensure that problems with the COM objects not destructing at the right time gets properly dealt with. This gets especially important when threads are to be garbage collected as everything is going to need to be collected in the right order.

Just as a final observation about JavaScript here's something that I'm sure Jonathan already knows.

function factorial( n ) {
    if ( n == 1 )
        return 1;
    else
        return n * factorial( n - 1 );
}
factorial.pure = true;

function main() {
    Mahlee.test( factorial( 6 ), 720 );
    Mahlee.test( factorial.pure, true );
}

Functions aren't just first order values in JavaScript, they are actually also objects. They do seem to have some special handling for this though as the following doesn't work and I'm not entirely sure why:

function factorial( n ) {
    this.executed = true;
    if ( n == 1 )
        return 1;
    else
        return n * factorial( n - 1 );
}
factorial.pure = true;

function main() {
    Mahlee.test( factorial( 6 ), 720 );
    Mahlee.test( factorial.pure, true );
    Mahlee.test( factorial.executed, true );
}

I'm planning to use this to make the futures that Mahlee returns a bit nicer syntactically whilst not losing the ability to return out of band information for error handling.


Categories: