Memory Leak from GenericChannel.initialize

I have noticed a small memory leak every time I call GenericChannel.initialize.

I added the following function to the MO2Sensor.mc example code to allow it to pair to a new sensor after it has already been paired to one.

function setPair()
{
closeSensor();
GenericChannel.release();
GenericChannel.initialize(method(:onMessage), chanAssign);

pairing = true;

deviceCfg = new Ant.DeviceConfig( {
:deviceNumber => 0, //Wildcard our search for pairing
:deviceType => DEVICE_TYPE,
:transmissionType => 0,
:messagePeriod => PERIOD,
:radioFrequency => 57, //Ant+ Frequency
:searchTimeoutLowPriority => 10, //Timeout in 25s
:searchTimeoutHighPriority => 2, //Timeout in 5s
:searchThreshold => 1} ); //Turn on Proximity Pairing
GenericChannel.setDeviceConfig(deviceCfg);

searching = true;
}


When the function is called repeatedly, the memory used grows by 243 bytes every time that GenericChannel.initialize is called.

Is this the correct way to pair to a new sensor or is there a better way that would not cause the memory used to grow like this? Is there something additional that needs to be closed out to prevent this?

I can send in more code if that would be helpful.
  • Former Member
    Former Member over 10 years ago
    I'm not seeing a constant increase with this code...

    function openCh() {
    System.println("Opening Ant channel. Freemem = " + System.getSystemStats().freeMemory);
    // Get the channel
    var chanAssign = new Ant.ChannelAssignment(
    Ant.CHANNEL_TYPE_RX_NOT_TX,
    Ant.NETWORK_PLUS);


    // Set the configuration
    var deviceCfg = new Ant.DeviceConfig( {
    :deviceNumber => 0,
    :deviceType => 120,
    :transmissionType => 0,
    :messagePeriod => 8070,
    :radioFrequency => 57,
    :searchTimeoutLowPriority => 2,
    :searchTimeoutHighPriority => 2,
    :searchThreshold => 0} );


    mAntCh = new Ant.GenericChannel(method(:onAntMsg), chanAssign);
    mAntCh.setDeviceConfig(deviceCfg);
    isChOpen = mAntCh.open();
    }


    Output...
    Opening Ant channel. Freemem = 37328
    Opening Ant channel. Freemem = 25496
    Opening Ant channel. Freemem = 25520
    Opening Ant channel. Freemem = 25496
    Opening Ant channel. Freemem = 25496
    Opening Ant channel. Freemem = 25496
    Opening Ant channel. Freemem = 25496
    Opening Ant channel. Freemem = 25520
    Opening Ant channel. Freemem = 25520
    Opening Ant channel. Freemem = 25496
    Opening Ant channel. Freemem = 25520
    Opening Ant channel. Freemem = 25520
    Opening Ant channel. Freemem = 25480
    Opening Ant channel. Freemem = 25504
  • I think the difference is that SHARKBAIT_AU is allocating the Ant.GenericChannel on the heap, and the example above seems to be inheriting from it. I think the explicit call to initialize() is probably a pretty good indicator that something is being used in an interesting way.

    Travis
  • Former Member
    Former Member over 10 years ago
    Had some food, & a refresh, I am amazed at some of the things I wrote earlier... anyways.

    After a quick delve into what are stack & heap, I find this in the guide
    .....all objects are allocated on the heap, .......Monkey Cdoes not have primitive types; integers and floats are objects. .......
    So everything is going in the heap, is it not?
  • Yes. Everything is on the heap, but I have doubts that the base class is stored on the heap separately from the derived.

    In the MO2Sensor.mc example code, the class MO2Sensor extends Ant.GenericChannel and explicitly initializes the base class from within the derived classes initialize method. I think this bit of code is fine. It is just initializing the base class as the language requires.

    The above setPair() attempts to allow the sensor pairing to happen again, and re-initializes the base class explicitly. It seems wrong to be calling initialize() from outside the extending classes initialize() method. I'm not claiming it is wrong (yet), but it does seem unusual.

    In this case the change to test is probably very simple. Declare a member that is the generic channel, and allocate a new GenericChannel instance in setPair().
  • Former Member
    Former Member over 10 years ago
    I think I'm getting all this. Because although the initialize method is included, it's intended functionality (I'm guessing) was to be used once. We have found we need to fully release the channel at the moment, because we are unable to reconnect if channel is closed then opened again. I might play with this some more and confirm that is still the case.
  • I did a bit more testing on this tonight. When I got this issue untangled from the other memory leak I reported on I found out that this memory leak only occurs on the simulator and not on the 920 watch itself.

    I'm still not sure that using the GenericChannel.initialize every time a new device is paired the way I did is intended functionality as SHARKBAIT's post above describes.

    Simulator
    Used: 56368
    Used: 57211
    Used: 57454
    Used: 57697
    Used: 57940
    Used: 58183

    Watch
    Used: 54024
    Used: 54064
    Used: 54040
    Used: 54040
    Used: 54040
    Used: 54040
    Used: 54064
    Used: 54040
    Used: 54040
    Used: 54040
    Used: 54040
    Used: 54016
  • Former Member
    Former Member over 10 years ago
    I'm not extending the genericChannel. When I run the following in the simulator I only get the extra bytes once.

    Note that I am checking the memory at Ant.MSG_CODE_EVENT_RX_SEARCH_TIMEOUT, so the first value is not a figure taken before initialization.

    function openCh() {
    mAntCh.initialize(method(:onAntMsg), chanAssign);
    isChOpen = mAntCh.open();
    }


    Usedmem = 27142
    Usedmem = 27385
    Usedmem = 27385
    Usedmem = 27385
    Usedmem = 27385
    Usedmem = 27385
    Usedmem = 27385
    Usedmem = 27385
    Usedmem = 27385
    Usedmem = 27385
  • Kyle has done a lot of work to isolate and eliminate memory leaks, so this may already be taken care of. Just to be sure, I've reported this for investigation.

    Thanks!
  • Just looking back to report that this was fixed in a 1.1.x release.