Are LiveAPI objects instantiated in JS garbage collected ?

Julien Bayle's icon

Hi there,

Creating an array of LiveAPI objects, I'd like to know if objects are really killed if I splice all elements of that array.
It doesn't seem from a performance/efficiency point of view.

Indeed, my liveset is ok, no lag nothing.
I put the device, if I build a lot of callback, it lags a very bit (only the audio meters)
If I click on my button which splices ALL object in the array, it still lags.
If I delete the device, then undo, no more lags.

any infos?

jamesson's icon

I would imagine that a formal declaration of array to be null (as opposed to calling methods to remove objects from the patcher) might help.

Could you post your code?

Julien Bayle's icon

Problem is:
I have an array with a length of n.

I decide to activate this or that parameters to be listened (= create the corresponding LiveAPI object w/its callback)
It puts it inside the array at the index 3 for instance.

Same with another one at index 5.

Then, I want to remove the object in 3 (= I don't want max to listen a specific parameter anymore)

tricky.

jamesson's icon

I still think my suggestion is worth a try.

Julien Bayle's icon

tried. same.

problem isn't the array but the objects which seem to remain in memory/cpu cycles or whatever.
sounds strange.
first time I experiment that

jamesson's icon

Could you post your code pls?

Thanks

Joe

amounra's icon

Live API objects aren't going to get collected, I think. Id's are persistent, even if no longer assigned (I asked someone about this before, but perhaps something has changed since then). I don't know how this figures into memory management within js, though.

One thing you can do is remove the callback from the API by assigning the object.property = 0. This generally gets rid of any overhead I have. Just removing the js object's assignment does NOT remove the API object itself, afaik.

After rereading your post, I think that's what you are after: reassign the .property of the object to 0.

a

btw, assignment of the array to null will lead to api errors (or at least it used to, the last time I tried it).

Julien Bayle's icon

for sure, it only remove the reference and garbage collection can happen but of course doesn't free the placeof the LiveAPI objects.
removing the callback doesn't help a lot as far as I tested.

I asked to Andrew who probably answer here.

thanks for the explorations :)

if you are interested by the purpose, you can check this :
http://julienbayle.net/2012/01/25/my-video-generator-global-architecture/

Zack's icon

I know this is an old post but I'm actually having a similar issue. I am instantiating a lot of LiveAPI objects in my javascript code, and eventually it starts to lag my ableton set. The problem is that I am also using lots of observers as well (and also Task objects), so it is hard to narrow down the exact cause of the lag in the code so far. The only way to fix it is to delete the max plugin and then undo, as Julien mentioned in his original post.
@JulienBayle, did you ever come up with a solution to the problem? Or does anyone else know?

petrus04's icon

@zack
you could call this simple function i wrote.

It works well. To call after any "new LiveApi" instance

function DestroyLiveApiObject(t)
{
    t.property = '';
    t.id = 0;
    t = null;
}


Silsen's icon

Thank you so much everyone for documenting this issue!I had the same problem of my max4live device slowing down the UI more and more, depending on how often I executed my js code. And then I also noticed that saving the max4live patch would get rid of the lag.

Using the function described by @PETRUS04 to destroy any "new LiveApi" instances at the right point in the code completely fixed my lag problems. Here's a small example:

function renameTrackClips(pathTrack) {
   var track = new LiveAPI(pathTrack);
   var trackName = track.get("name");
   renameClips(pathTrack, trackName);
   DestroyLiveApiObject(track);
}
Sonoran Music Devices's icon

I have researched this question EXTENSIVELY, and I want to ask the community: what is the ultimate best practice for cleaning up LiveAPI objects? Below is some context and my opinion on the matter.

From what I can tell, LiveAPI objects ARE garbage collected. Even callbacks are gone after restarting Live and reloading the Live set.

In JavaScript, when objects go out of scope, they are garbage collected. Even @Jeremy (ostensibly a C74 developer) says so in this post, and he uses an array to try to PREVENT that from happening.

I suspect a lot of the performance issues people think they are having more recently with LiveAPI objects and callbacks are due to the fact that LiveAPI objects run in the low priority thread or something else. Regarding the issues the original posters in this thread from 13 years ago were experiencing, IIRC I read somewhere that there was a memory leak bug in the LiveAPI that was fixed, and it is possible that was the root cause of those older issues.

The big reason I am asking this question is I actually ran into an issue using a similar DestroyLiveApiObject() function as described in this thread. It generally works fine, but trying to use it to destroy a LiveAPI object with a callback is problematic. That is, calling the function inside the callback causes weird issues - even when forcing it to deferlow. In my case, since it cannot be done inside the callback, the next best thing is to do it the next time the Live set reloads.

Finally, from what I can tell, none of the official documentation says anything about destroying LiveAPI objects.

So...given all of the above, I am kind of thinking it is unnecessary to worry about destroying LiveAPI objects. As long as low priority expectations are managed, then LiveAPI objects will be garbage collected, and there should not be any need to destroy callbacks, since they are neither CPU nor memory intensive (given that I agree with Tyler's assessment below).

As @tyler mazaika points out in this post:

In particular having lots of observers on properties which only rarely change doesn't strike me as something that should have a significant cpu hit. They respond to notifications rather than poll for changes, no?

Any thoughts?

Am I on track here?

Julien Bayle's icon

13 years later, coming back on this thread.

CPU wise, I'm not sure, indeed, that it really frees anything
Live API wise, I still "destroy" using the destroy way described here in order to "remove" callbacks and actions they can trigger back.

I don't know if things have been really documented somewhere since.

Sonoran Music Devices's icon

Live API wise, I still "destroy" using the destroy way described here in order to "remove" callbacks and actions they can trigger back.

That used to be my plan until, as I described above, l ran into issues doing it from a callback. Then I thought the next and only logical place to do it would be the next time the Live set reloads. Then I realized that was unnecessary, since the objects and even registered callbacks are gone after restarting Live and reloading the Live set.

In yesterday's Live 12.2 beta release, I saw the below release notes, and that makes me wonder if that would have fixed the issue I was having destroying LiveAPI objects in callbacks. At this point, I am probably not going to bother testing it out, since I feel confident that it is unnecessary.

v8: fixed crash in LiveAPI callback

v8: fixed crashes with LiveAPI callbacks

Julien Bayle's icon

BTW, official max for live version is still 8.x.x

I'm currently in the middle of a book writing and teaching sessions, and we started to use 9 for that too. Working fine and didn't notice so much issues. At some point, we'll go with 9 engine even if still not official.

Sonoran Music Devices's icon

Version 9 in Live seems imminent, since it is now the version bundled in the most recent Live beta.

Julien Bayle's icon

Indeed. Also part of beta testers here & there.

Connor Shafran's icon

Does anyone have any updates on this since last year? I'm turning in circles, chasing my tail, trying for two days now to find the reason that my JS script seems to progessively slow Ableton down the more I use it.

My theory has been that creating lots of Live API Objects is creating some kind of clutter, but a few tests seem to show that it actually doesn't matter how many objects are created...?

This seems to be one of those haunted problems?

Any advice or updates on the garbage collection topic in general would be greatly appreciated!

(Edit: I'm on Live 12.3 using the built-in Max 9.0.9. I've tried both V8 and JS and it doesn't seem to make any difference.)

Julien Bayle's icon

As I've experienced over the last 14 years with these "haunted" lag issues, the problem isn't usually the JS memory heap—it's the C++ observer overhead in Live's engine. Even if the JS object is gone, the "hook" seem to persist.... Seem.

Based on what has worked in my own sessions and projects, here is how I'd suggest handling LiveAPI in Max 9:

  • Simply setting an object to null is not enough. You must manually detach the observer from the Live engine before losing the reference.

function destroyApiObject(apiObj) {
    if (apiObj) {
        apiObj.property = ""; // Crucial: removes the callback from Live's engine
        apiObj.id = 0;        // Detaches the proxy
        apiObj = null;        // Permits JS garbage collection
    }
}
  • Recycle via Object Pooling

    Avoid using new LiveAPI() inside loops or high-frequency functions. This is the #1 cause of progressive UI lag.

    • Instead: Create a small "pool" of LiveAPI objects at the top level of your script.

    • Action: Simply update their .id or .path when you need to point them elsewhere. This keeps the engine's observer list stable, as far as I observed...

  • Manage the "Zombie Task"

    If you use Task objects alongside LiveAPI, they can continue firing in the background even if the logic they point to is broken. Suggestion: Always call this.patcher.getnamed("myTask").cancel() or handle task cleanup in your save or close logic.

  • The "Delete-Undo" Reality Check

    If deleting and undoing the device fixes the lag, your script has leaked observers. Live seems to only clear these specific C++ hooks when the device instance itself is destroyed. If this is happening, audit your code for any new LiveAPI calls that don't have a corresponding property = "" cleanup.

Let us know.

Connor Shafran's icon

Hi Julien,

thanks for the quick reply!

This all makes sense, and lines up with what I already suspected. However, I'm not using any observers with properties in my JS script – only live objects, with set/call/get commands.

Still – I'm already setting unused LiveAPI objects to .id = 0 whenever they're no longer used or when their corresponding objects/clips in Ableton are deleted, just in case.

I'm also already 'recycling' live objects, continuously switching their .id/.path, rather than creating new ones (whenever possible).

Regarding 'zombie tasks' – I'll have to look into that.

The classic delete-undo trick doesn't fix the issue, so I'm pretty sure it's not leaks/pileup inside the JS.

I'm starting to think I'm hallucinating the whole thing. 🫠😵‍💫