Find Loitering Objects with Adobe Scout

Posted on August 7, 2013 | 2 comments

Adobe Scout is a powerful profiling tool for Adobe Flash Player and Adobe AIR based content. In the recent update to Scout (version 1.1) developers have the ability to profile memory allocation. Most developers want an ability to basically find their memory leaks easily.

The old Flash Builder profile made it fairly easy to find loitering objects. Loitering objects where a set of object allocations that between two memory snapshots have not been recovered by the garbage collector (GC). Typically if you have loitering objects you have references to those objects somewhere in the application that keep those objects from being collected by GC. Developers want to quickly find those objects, where they were allocated, and finally what references are keeping them around.

Adobe Scout can help with the first two, finding loitering objects and where they are allocated, but currently doesn’t help with figuring out what references are keeping the objects around. In this post I want to show you how to use Adobe Scout to loitering objects and where they are allocated.

Adobe Scout Settings

First make sure that the Flash Player or AIR content has the -advanced-telemetry option is enabled, Scout has Memory Allocation Tracking checked, and for the Web you need to run the debug player (not needed for AIR).

Adobe Scout Memory Allocation Tracking Setting

Running Test Code

I have created a basic ActionScript 3 project with code that will demonstrate a loitering objects scenario. You can get the ScoutMemory project on GitHub here. This project consists of two classes. The main class waits 1s then creates 10,000 objects and pushes them into a Vector collection that will be nulled out later. The main class also adds 2000 of those same objects instances into a Vector on a basic second class that will keep the reference of those objects around.

Here is what the code looks like:

package
{
import flash.display.Sprite;
import flash.utils.setTimeout;

public class ScoutMemory extends Sprite
{
    public function ScoutMemory()
    {
        referenceHog = new ReferenceHog();
        setTimeout(createObjects, 1000);
    }
   
    private var pool:Vector.<Object>;
    private var loops:int = 0;
    private var referenceHog:ReferenceHog;
   
    private function createObjects():void
    {
        loops++;
        pool = new Vector.<Object>();
        var count:int = 10000;
        for (var i:int = 0; i < count; i++)
        {
            var o:Object = new Object();
            if (i % 5 == 0)
                referenceHog.keepReferencePool.push(o);
            pool.push(o);
        }
        setTimeout(removeObjects, 1000);
    }
   
    private function removeObjects():void
    {
        pool = null;
        if (loops < 2)
        setTimeout(createObjects, 1000);
    }
}
}
package
{
public class ReferenceHog
{
    public function ReferenceHog()
    {
    }
   
    public var keepReferencePool:Vector.<Object> = new Vector.<Object>();
}
}

The application runs, after 1s it creates objects, after another second it nulls out the pool Vector instance, and then does it again. The objects that are passed into the ReferenceHog’s
keepReferencePool Vector will keep a total of 4000 objects (10k % 5 * 2 = 4k) around in memory. Let’s see how to see this in Scout.

Open Adobe Scout, and then run the ScoutMemory project in debug mode. Let it run a few seconds. With the application running do the following Scout:

  1. Click on the Frame Timeline panel, and then select all frames Edit -> Select All (or Ctrl – A)
  2. Click on the Summary panel, and then the Frame Time subpanel, and then select the Other -> Garbage Collection line item to have Scout only highlight Scout data with Garbage Collection items (orange color).
  3. Click on the Memory Allocation panel, and then click the Force Garbage Collection button a few times (usually twice works for me). This forces GC to clean up any objects.
  4. Force Garbage Collection

  5. In the Memory Allocation panel select the Allocations option in the first dropdown, Bottom-Up Functions in the second dropdown, enable both buttons (Hide Garbage-Collected Objects and Expand/Collapse All)
  6. Stop the Scout capture or just close the application

Here is the full screenshot of what my Scout session looks like:
Scout Memory Session

By selecting all frames of my session I am affectively comparing a memory snapshot from the first frame to the last frame. I am viewing all the allocations that have not been garbage collected which gives me the loitering objects. The “Bottom-Up Functions” option gives me a quick view of where these objects are being allocated. But like I mentioned above it doesn’t show me that those 4000 objects are not being GC’d because the are referenced in the ReferenceHog.keepReferencePool Vector property.

I suggest filtering the orange colored Frame Time -> Other -> Garbage Collection line item is so if you can easily see in what frames GC is happening and check out specific frames. It’s a nice way to look at where that is happening.

You can also check out the Scout session file here if you just want to play with Scout settings without running the code. You can get that .flm file here.

  • emil

    Really nice example of the benefit of loitering objects.

  • Alex Morozov

    Thanks, this article helped me with profiling=)