Discussion on Memory Model of JSB

136 views
Skip to first unread message

huabi...@cocos2d-x.org

unread,
Aug 1, 2014, 1:57:33 PM8/1/14
to cocos2d-...@googlegroups.com, Ricardo Quesada, Gary Liu, lin...@cocos2d-x.org

The original idea was to remove "retain/release" in JSB to provide a better user experience for JS users.


1. Background:


Currently, SpiderMonkey and Cocos2d-x have two separated garbage collection system. SpiderMonkey has the normal auto GC system while Cocos2d-x use its reference count based GC.


In JSB, all engine objects is managed by Cocos2d-x GC once they are added into the scene graph or engine managers, the corresponding js objects will be added to SpiderMonkey’s root so that they won’t be released by SpiderMonkey. There are two important issues related to this system.


- Engine objects that haven’t been added to the scene graph or engine managers will be released by Cocos2d-x’s GC. But the js objects still exist, if user try to access them, there will be an “Invalid native object” error raised.


- Many developers reported that there are memory leaks for objects which have been added into the root of SpiderMonkey.


For the first problem, the current solution is using retain / release functions to manually manage the object in js. But for the second problem, it’s related to our solution and it’s not easy to solve.


2. New proposition:


There have been a new proposition which is to reverse the current control direction, instead of control object life cycle with Cocos2d-x's reference counting system, we can use SpiderMonkey's GC to control native object's life cycle. To achieve that, basically we retain the native object during creation, and SpiderMonkey will invoke a GC hook while a js object is being garbage collected, and in this callback we release the native object.

After a couple days of research, Qingkui HU and I found some important issues about this solution:

- Object ownership created by "addChild" or other native functions doesn't exist in JS, because the action which add child node to parent node was 100% in C++ code, so for JS, they are always two object without any relationship. That will cause many inappropriate garbage collection.

- Finalize function of inherited classes in JS won't trigger during SpiderMonkey's GC, I have described this issue in another topic

- An JS object may remain it's existence until next GC even if it's no longer used, this will cause native object remains alive, potential issues can happen with Scheduler, EventDispatcher, etc.

- SpiderMonkey's GC often happens while the memory usage is crucial, which is not a good timing, so user may need to call GC function by themselves.

The solution for the first problem could be creating the link during such functions, but I straggle a lot for solving the second one, and the third/fourth problems still remains to be tested.

3. Help~~~~~~

So I want to know what do you think about it ? 
Do you have any suggestions on these issues ? 
Do you support the new proposition or the current one ?

If there is some missed point or if you want any additional informations, please also reply to me.
Thanks for any kind of help!

Best regards

Huabin LING

Hex Lee

unread,
Aug 8, 2014, 2:54:35 AM8/8/14
to huabi...@cocos2d-x.org, cocos2d-...@googlegroups.com, Ricardo Quesada, Gary Liu, Shun Lin
we should add a destruct method named "dtor" for js layer object,  you can release some js layer object or refrence in it on you certainly sure a js object no longer needed.
we can add it in CCNode,  then all object extends CCNode should have this method, here is example:

----------->
uw.CustomLayer = cc.Layer.extend({
    _someArr: []
    _someNodes; []
    init: function () {
        this._super();
        ...
     },

     onExit: function(){
         // if need
         this.dtor();
     }

    dtor:function(){
        this._super();
        _someArr = null;
        while(_someNodes.length){
            var node = _someNodes.pop();
            // if need
            node.dtor()
        }
        _someNode = null;
    }
});


<-------------


--
You received this message because you are subscribed to the Google Groups "cocos2d JS development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cocos2d-js-dev...@googlegroups.com.
To post to this group, send email to cocos2d-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ricardo Quesada

unread,
Aug 21, 2014, 6:47:53 PM8/21/14
to Hex Lee, LING HUABIN, cocos2d-...@googlegroups.com, Gary Liu, Shun Lin
Hi,

good points.

From the 4 issues that you mention, I'm only worried about the 1st one: addChild().
The 2nd one, I guess it is a bug in SpinderMonkey or in our code.
The 3rd one is fixed by calling the GC manually. In fact, this MUST be done by game developers when a new Scene is executed. No matter which memory model they use, the GC must be manually called when the game is non running like: menu scene, game over dialog, etc...
The 4th one is same as 3rd one. The GC must be called manually.


So, regarding the 1st one, how to solve it ? any ideas ?
Should the we manually increment the JS Ref Count in the JS_addChild() ?
Other alternatives ?




Reply all
Reply to author
Forward
0 new messages