Loading ...
Sorry, an error occurred while loading the content.

Frustrations with the profiler - analyzing memory usage.

Expand Messages
  • Nigel Magnay
    We have an application that is leaking memory. Sadly, trying to diagnose this with the flex profiler (4.6, 4.7) is proving to be a frustrating experience. I ve
    Message 1 of 4 , Feb 5, 2013
    • 0 Attachment
      We have an application that is leaking memory. Sadly, trying to diagnose this with the flex profiler (4.6, 4.7) is proving to be a frustrating experience.

      I've picked on one object class to try and understand what is going on. We have a wizard-style dialog box with a sidebar control 'wizardlinks' which adds 'wizardlink' objects to it. Both are Spark group controls. The links are being added to the group with an 'addElement' call.

      The WizardLink instances are growing in memory and do not seem to be being released. I've pared them right down to try and eliminate possible listeners.

      If I immediately remove the link, Something still seems to hold on to it. If I view it in the profiler object view, it expands saying (1 Path) but won't describe what it is. Even more mysteriously - if I run with "Watch live memory data", I can see the instances going up -- but if I then do a memory dump, those instances are now missing. If I don't run with 'watch live memory data', they are there.

      Part of this feels like chasing shadows - are these real leaks, or just things the collector will eventually get round to? 


    • Alex Harui
      The true test of a leak is whether your OS’s process manager says that memory consumption keeps going up. Before we had a profiler, we would add code to the
      Message 2 of 4 , Feb 5, 2013
      • 0 Attachment
        Re: [flexcoders] Frustrations with the profiler - analyzing memory usage. The true test of a leak is whether your OS’s process manager says that memory consumption keeps going up.

        Before we had a profiler, we would add code to the app to exercise some sequence (by faking button events, etc), force garbage collection, and report System.totalMemory over and over again and run it overnight.  Due to the way Flash manages memory, just manually exercising the sequence a few dozen times may show increasing memory even though there isn’t a leak, although really bad leaks will show up in System.totalMemory or in the OS process manager pretty quickly.  Leaky apps will eventualy crash the browser, or just report an endless increase in memory, way past what you would expect for an app of that size and complexity.

        Historically, the profiler has shown a dependency on the version of the Flash Player.  Whatever version of Flash Player is recommended for the default SDK in your version of Flash Builder should be the one to use when profiling.  Newer and older versions may report memory slightly differently and fool the profiler.

        HTH,
        -Alex

        On 2/5/13 5:57 AM, "Nigel Magnay" <nigel.magnay@...> wrote:


         
         
           

        We have an application that is leaking memory. Sadly, trying to diagnose this with the flex profiler (4.6, 4.7) is proving to be a frustrating experience.

        I've picked on one object class to try and understand what is going on. We have a wizard-style dialog box with a sidebar control 'wizardlinks' which adds 'wizardlink' objects to it. Both are Spark group controls. The links are being added to the group with an 'addElement' call.

        The WizardLink instances are growing in memory and do not seem to be being released. I've pared them right down to try and eliminate possible listeners.

        If I immediately remove the link, Something still seems to hold on to it. If I view it in the profiler object view, it expands saying (1 Path) but won't describe what it is. Even more mysteriously - if I run with "Watch live memory data", I can see the instances going up -- but if I then do a memory dump, those instances are now missing. If I don't run with 'watch live memory data', they are there.

        Part of this feels like chasing shadows - are these real leaks, or just things the collector will eventually get round to?



           



        --
        Alex Harui
        Flex SDK Team
        Adobe Systems, Inc.
        http://blogs.adobe.com/aharui
      • Nigel Magnay
        Thanks for that - that s very helpful information. I m getting dragged into diagnosis because on very low-spec machines our app is tending to eat memory
        Message 3 of 4 , Feb 6, 2013
        • 0 Attachment
          Thanks for that - that's very helpful information. 

          I'm getting dragged into diagnosis because on very low-spec machines our app is tending to eat memory causing it to heavily slow down. I've managed to diagnose some of these (use of setTimeout, Bindings that never go away) which is liable to help hugely.

          What I'm having difficulty in is determining what things in the profiler are genuine leaks, and what things are things the GC will eventually get to as they're weak references (I do the System.gc() and new LocalConnection().connect('foo'); tricks beforehand, but they don't feel like they're reliable. It's a shame there isn't a System.reallyreallyfullGCandIDontCareHowLongItTakes() )

          A good example is mx.core:EmbeddedFont. When the app is in use, this number doubles. So I analyse an instance, and find only 1 path - which it states as simply "mx.core:EmbeddedFont (1 Path), GC Root=YES" and allocated in "mx.core:EmbeddedFontRegistry:GetAssociatedModuleFactory()".

          What I believe that's telling me is that the reference is there because of the static EmbeddedFontRegistry in EmbeddedFont, and it's being stored in that registry in a cache (cachedFontsForObjects) - which is a weak dictionary.

          My gut instinct at this point is "this is irrelevant, it'll get GCed eventually". Two things strike me though
            - I'm guessing that it's in that dictionary as the object reference view stops at the EmbeddedFont, which seems a shame. That makes it difficult in any code that's pretty complex
            - I'm guessing it'll be GCed. But I wonder now if all those things will be GCed eventually. Why didn't the 'invoke GC' parts actually cause it to be collected..



          t
          On Tue, Feb 5, 2013 at 7:32 PM, Alex Harui <aharui@...> wrote:
           

          The true test of a leak is whether your OS’s process manager says that memory consumption keeps going up.

          Before we had a profiler, we would add code to the app to exercise some sequence (by faking button events, etc), force garbage collection, and report System.totalMemory over and over again and run it overnight.  Due to the way Flash manages memory, just manually exercising the sequence a few dozen times may show increasing memory even though there isn’t a leak, although really bad leaks will show up in System.totalMemory or in the OS process manager pretty quickly.  Leaky apps will eventualy crash the browser, or just report an endless increase in memory, way past what you would expect for an app of that size and complexity.

          Historically, the profiler has shown a dependency on the version of the Flash Player.  Whatever version of Flash Player is recommended for the default SDK in your version of Flash Builder should be the one to use when profiling.  Newer and older versions may report memory slightly differently and fool the profiler.

          HTH,
          -Alex



          On 2/5/13 5:57 AM, "Nigel Magnay" <nigel.magnay@...> wrote:


           
           
             

          We have an application that is leaking memory. Sadly, trying to diagnose this with the flex profiler (4.6, 4.7) is proving to be a frustrating experience.

          I've picked on one object class to try and understand what is going on. We have a wizard-style dialog box with a sidebar control 'wizardlinks' which adds 'wizardlink' objects to it. Both are Spark group controls. The links are being added to the group with an 'addElement' call.

          The WizardLink instances are growing in memory and do not seem to be being released. I've pared them right down to try and eliminate possible listeners.

          If I immediately remove the link, Something still seems to hold on to it. If I view it in the profiler object view, it expands saying (1 Path) but won't describe what it is. Even more mysteriously - if I run with "Watch live memory data", I can see the instances going up -- but if I then do a memory dump, those instances are now missing. If I don't run with 'watch live memory data', they are there.

          Part of this feels like chasing shadows - are these real leaks, or just things the collector will eventually get round to?



             



          --
          Alex Harui
          Flex SDK Team
          Adobe Systems, Inc.
          http://blogs.adobe.com/aharui


        • Alex Harui
          I have never seen the localconnection hack fail to GC everything, but it has been over a year since I was last in the profiler, so maybe more recent players
          Message 4 of 4 , Feb 6, 2013
          • 0 Attachment
            Re: [flexcoders] Frustrations with the profiler - analyzing memory usage. I have never seen the localconnection hack fail to GC everything, but it has been over a year since I was last in the profiler, so maybe more recent players don’t GC everything, but I would be surprised if that was the case.  That’s because the LC hack wasn’t supposed to GC everything, but once we discovered it did, the FP team felt like they couldn’t change that behavior.

            I have seen different player versions cause the profiler to report things as being around when they aren’t or have it seem like the GC button in the profiler doesn’t work, but we tend to get that resolved for each new FB version.  Then newer players come along and it seems to go funky again.  That’s why you should make sure you are using the right player for your FB version.

            I have never seen weak references not work correctly, so you probably don’t need to chase paths beyond weak references.

            EmbeddedFonts are not leaking per-se.  They are sticking around because a display object that uses embedded fonts is stuck.  I usually look for big things (views/containers/navigators for example).  A common workflow for me is to exercise the app, take a memory snapshot, exercise the app some more, take another snapshot, sort both snapshots alphabetically, and manually compare the number of live instances.  LoiteringObjects can show you false positives in some scenarios so I often do manual compares.  If the number of big things is increasing, I look there first.  Of course, it could be a child that is stuck because children reference their parents.  And maybe you’ll get lucky and see that timers or intervals are increasing.


            On 2/6/13 12:48 AM, "Nigel Magnay" <nigel.magnay@...> wrote:


             
             
               

            Thanks for that - that's very helpful information. 

            I'm getting dragged into diagnosis because on very low-spec machines our app is tending to eat memory causing it to heavily slow down. I've managed to diagnose some of these (use of setTimeout, Bindings that never go away) which is liable to help hugely.

            What I'm having difficulty in is determining what things in the profiler are genuine leaks, and what things are things the GC will eventually get to as they're weak references (I do the System.gc() and 
            new LocalConnection().connect('foo'); tricks beforehand, but they don't feel like they're reliable. It's a shame there isn't a System.reallyreallyfullGCandIDontCareHowLongItTakes() )

            A good example is mx.core:EmbeddedFont. When the app is in use, this number doubles. So I analyse an instance, and find only 1 path - which it states as simply "mx.core:EmbeddedFont (1 Path), GC Root=YES" and allocated in "mx.core:EmbeddedFontRegistry:GetAssociatedModuleFactory()".

            What I believe that's telling me is that the reference is there because of the static EmbeddedFontRegistry in EmbeddedFont, and it's being stored in that registry in a cache (cachedFontsForObjects) - which is a weak dictionary.
            My gut instinct at this point is "this is irrelevant, it'll get GCed eventually". Two things strike me though
              - I'm guessing that it's in that dictionary as the object reference view stops at the EmbeddedFont, which seems a shame. That makes it difficult in any code that's pretty complex
              - I'm guessing it'll be GCed. But I wonder now if all those things will be GCed eventually. Why didn't the 'invoke GC' parts actually cause it to be collected..



            t
            On Tue, Feb 5, 2013 at 7:32 PM, Alex Harui <aharui@...> wrote:
             
             
             
               

            The true test of a leak is whether your OS’s process manager says that memory consumption keeps going up.

            Before we had a profiler, we would add code to the app to exercise some sequence (by faking button events, etc), force garbage collection, and report System.totalMemory over and over again and run it overnight.  Due to the way Flash manages memory, just manually exercising the sequence a few dozen times may show increasing memory even though there isn’t a leak, although really bad leaks will show up in System.totalMemory or in the OS process manager pretty quickly.  Leaky apps will eventualy crash the browser, or just report an endless increase in memory, way past what you would expect for an app of that size and complexity.

            Historically, the profiler has shown a dependency on the version of the Flash Player.  Whatever version of Flash Player is recommended for the default SDK in your version of Flash Builder should be the one to use when profiling.  Newer and older versions may report memory slightly differently and fool the profiler.

            HTH,
            -Alex



            On 2/5/13 5:57 AM, "Nigel Magnay" <nigel.magnay@... <http://nigel.magnay@...> > wrote:


             
             
               

            We have an application that is leaking memory. Sadly, trying to diagnose this with the flex profiler (4.6, 4.7) is proving to be a frustrating experience.

            I've picked on one object class to try and understand what is going on. We have a wizard-style dialog box with a sidebar control 'wizardlinks' which adds 'wizardlink' objects to it. Both are Spark group controls. The links are being added to the group with an 'addElement' call.

            The WizardLink instances are growing in memory and do not seem to be being released. I've pared them right down to try and eliminate possible listeners.

            If I immediately remove the link, Something still seems to hold on to it. If I view it in the profiler object view, it expands saying (1 Path) but won't describe what it is. Even more mysteriously - if I run with "Watch live memory data", I can see the instances going up -- but if I then do a memory dump, those instances are now missing. If I don't run with 'watch live memory data', they are there.

            Part of this feels like chasing shadows - are these real leaks, or just things the collector will eventually get round to?



               



            --
            Alex Harui
            Flex SDK Team
            Adobe Systems, Inc.
            http://blogs.adobe.com/aharui
          Your message has been successfully submitted and would be delivered to recipients shortly.