Does node.removeFromParent actually cleanup node from memory

Hi guys,

I’m wondering does node.removeFromParent actually cleanup node from memory. I debugged my game on web, tracking CCNode count and the value is not decreased after I called removeFromParent.
Then I tried testing by calling node.destroy() before remove it from parent, the debug log show CCNode count decreased

If you keep a reference to node you just removed by calling removeFromParent, you can bring it back into scene by setting it’s parent. But if you destroy it, then it gets invalidaded and throws an exception if you try to set it’s parent.
So yeah, if you want to get rid of a node forever, you’d better destroy it. Otherwise it may seem that you’re leaking memory from your perspective

Yes I do have memory leak problem. As API document say, it should remove the node when I called removeFromParent

Hmm, it looks to me that removeFromParent only detaches node from it’s parent, but the node itself remains. I would suggest you try using destroy method for deleting nodes you no longer use

yeah. But please check the API document. removeFromParent method have an input parameter to state that the node should be cleanup. If you don’t pass any value, default value is TRUE

I’m also waiting for solution for another problem, I posted it here Memory not being cleared when moving between scenes
Have you ever dealt with same problem?

I only use cc.director.loadScene method, don’t use PUSH and POP scene methods

API reference states about cleanup argument: “If cleanup is true, then also remove all actions and callbacks.” I take it as “should engine also stop all activity that node is currently running? (animations and such)”. From my point of view such question implies, that this method is not supposed to destroy node.
No, I’ve never run into any issues with memory consumption, although I only work with web desktop target platform. If I am right, that could be your problem - nodes you thought you destroyed are actually bundling up somewhere out of your reach (at least through the scene graph)

I have discovered that destroy may not even do the job. If I put an event listener on a Component like so:

cc.eventManager.addCustomListener("foo", this.foo.bind(this));

And then later I call both this.node.removeFromParent and this.destroy, the Component will still respond to the event foo.

That’s because of how garbage collection works in javascript.
this.foo.bind(this) is a function-typed object that you pass to cc.eventManager which in turn keeps a reference to it. The component however, has no knowledge of this callback, despite it being derived from component’s function. So when component gets destroyed, it has no way to delete this eventListener unless you do it explicitly in Component.onDestroy
If you destroy node leaving event listener, this.foo.bind(this) and whatever data it enclosed as a scope will remain in memory, but only as JavaScript objects. Nodes, Components and other Cocos stuff will be invalidated and removed from engine update cycle

Is there a better alternative to using bind? Should I be using an anonymous function, or ES6 () => this.foo?

You should remove eventListener you’ve created when you no longer need them.
Engine treats event listeners as ‘function to be called on event’, it has no ‘function’s owner’ semantic. So eventManager cannot understand on it’s own that your custom event listener is no longer valid when your destroy your node.
But a reference to function is retained, so whatever objects required to execute this function normally (from JavaScript point of view) remain in memory.
If your event listener then will try do something meaningful to a node already destroyed, you’ll get Cocos error stating that a node is no longer valid

Thanks @persy, that really helped. Looking at a heap snapshot, if I don’t remove the event listener, the Node and the Component stay around in memory. Once I remove the event listener, they get garbage collected.

How can I use PUSH and POP in Creator?