Memory leak in CCNode

I have a game that uses particlesystems. Each time the player finishes a level, either by failing or succeeding, he can choose to replay that level. I then remove all children and eventlisteners and rebuilds the level by adding them again.
What I have found is that for each iteration the memory keeps increasing, of course indicating a memory leak.
After digging through the issue using Xamarin Profiler I have narrowed it down to mostly being due to an increasing amount of unreleased EventHandlers, specifically the eventhandler that is assigned to LayerVisibleBoundsChanged in the setter for Layer in CCNode - and since I am using particle systems this EventHandler is set a lot.

Am I releasing the child nodes in the wrong way or should the Layer be set to null in CCNode.Cleanup (ie bug in CocosSharp)?

Posts

  • rene_ruppertrene_ruppert DEXamarin Team, University, XamUProfessors Xamurai

    @JohanHgfeldt.1688‌ Can you provide a simple contained example project to replicate the issue?

  • Yes, attached is a simple solution with a CCParticleSnow instance. Each time you tap the screen it is regenerated. If you run the profiler you will notice there are about 1000 EventHandlers initially. After the first tap it will go up to about 3000, the next time 6000, then 11 000 etc. There are some other thing to look at as well I think - it is not only EventHandlers that are causing memory leaks, but they are the most obvious culprit.

  • kjpou1kjpou1 LUMember, Xamarin Team Xamurai

    Thanks @JohanHgfeldt.1688‌

    We will take a look at it. I have set up an issue to track this.

  • kjpou1kjpou1 LUMember, Xamarin Team Xamurai

    Hey @JohanHgfeldt‌

    One of the Event Listeners is not a problem

                          var touchListener = new CCEventListenerTouchAllAtOnce ();
                          touchListener.OnTouchesEnded = (touches, ccevent) => {
                              Restart();
                          };
                          AddEventListener (touchListener, this);
    

    If you move the previous code snippit up to the constructor it does not get attached again after

            protected void Stop()
            {
                RemoveAllChildren(true);
                ---> RemoveAllListeners (); <----
            }
    
  • In my real application I need to do that of various reasons so I did the same in this to mimic behaviour of adding all sprites and all event listeners again on each restart. But that listener is not what is causing the memory leak as you will notice if you look at the details in the profiler - it is the one attached to LayerVisibleBoundsChanged that is added in thousands and never released.

  • kjpou1kjpou1 LUMember, Xamarin Team Xamurai

    Yes very true and realise that. Was just the easiest to test right now ;-). I have something working now but needs more testing.

  • kjpou1kjpou1 LUMember, Xamarin Team Xamurai

    @JohanHgfeldt‌

    The issue mentioned previously should be fixed by the following commit.

    Thank you very much for finding and reporting the issue and specially using the awesomeness of the Profiler. That really helped recreating what you reported.

    Also, just as a side note and I know you sent that as an example to demonstrate the problem but in your code you have the following:

                snow = new CCParticleSnow(new CCPoint(this.ContentSize.Center.X, this.ContentSize.Height));
    

    could be replaced by:

                if (snow == null)
                    snow = new CCParticleSnow(new CCPoint(this.ContentSize.Center.X, this.ContentSize.Height));
                else
                    snow.ResetSystem();
    

    The RemoveAllChildren(true); specifying to cleanup children does not dispose of the children themselves so it is still usable. That way the particle system is not recreated multiple times.

    Here is the test results after fixing the cleanup to remove themselves when removal is specified with cleanup = true.

     SceneViewportChanged
    
    ----------- Init Begin ---------
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    ----------- Init End ---------
    [Mono] DllImport searching in: 'libGLESv2.dll' ('./libGLESv2.so').
    [Mono] Searching for 'glBufferSubData'.
    [Choreographer] Skipped 92 frames!  The application may be doing too much work on its main thread.
    [AudioTrack] did not receive expected priority boost on time
    ----------- Stop Begin ---------
    25
    24
    23
    22
    21
    20
    19
    18
    17
    16
    15
    14
    13
    12
    11
    10
    9
    8
    7
    6
    5
    4
    3
    2
    1
    ----------- Stop End ---------
    ----------- Init Begin ---------
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    ----------- Init End ---------
    ----------- Stop Begin ---------
    25
    24
    23
    22
    21
    20
    19
    18
    17
    16
    15
    14
    13
    12
    11
    10
    9
    8
    7
    6
    5
    4
    3
    2
    1
    ----------- Stop End ---------
    ----------- Init Begin ---------
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    ----------- Init End ---------
    
    
        LayerVisibleBoundsChanged
        ----------- Init Begin ---------
        0
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        ----------- Init End ---------
        [Mono] DllImport searching in: 'libGLESv2.dll' ('./libGLESv2.so').
        [Mono] Searching for 'glBufferSubData'.
        [Choreographer] Skipped 99 frames!  The application may be doing too much work on its main thread.
        [AudioTrack] did not receive expected priority boost on time
        ----------- Stop Begin ---------
        24
        23
        22
        21
        20
        19
        18
        17
        16
        15
        14
        13
        12
        11
        10
        9
        8
        7
        6
        5
        4
        3
        2
        1
        0
        ----------- Stop End ---------
        ----------- Init Begin ---------
        0
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        ----------- Init End ---------
        ----------- Stop Begin ---------
        24
        23
        22
        21
        20
        19
        18
        17
        16
        15
        14
        13
        12
        11
        10
        9
        8
        7
        6
        5
        4
        3
        2
        1
        0
        ----------- Stop End ---------
        ----------- Init Begin ---------
        0
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        ----------- Init End ---------
    
  • Awesome, thank you! Feels good to be contributing to a great products greatness. When will it be a part of the Nuget packages?

  • kjpou1kjpou1 LUMember, Xamarin Team Xamurai

    Not sure yet when we will be laying down another release right now. We are shooting for every two to three weeks.

Sign In or Register to comment.