Understanding Connect IQ device memory limits

I've only been coding Connect IQ apps for a few months so I'm still pretty green, but I'm hoping someone can help me understand memory limits, and what appears to be strange memory-related behavior. My first question is - does there exist a reference that documents the available memory for each Connect IQ device? The only thing I've seen are the values in the 'devices.xml' file which appears to be used by the device simulator to mimic the behavior and capabilities of each device. So I'm guessing that these values are representative of those which apply to the associated hardware devices?

Thus far I'm only working with / coding for the Epix device. From the 'devices.xml' file:

<app id="watchface" memory_limit="1048576" />
<app id="watch-app" memory_limit="1048576" />
<app id="widget" memory_limit="1048576" />
<app id="datafield" memory_limit="131072" />

This would seem to imply that a data field could be up to about 128K, while watch faces, applications and widgets could be almost 1MB. I've created a (very) complex data field which is working on the Epix. An example of reported memory values when the data field loads:

Memory used = 60952kb, free = 70104kb, total = 131072kb

So far so good, and this gives me the (apparently false ;-) sense that I've still got plenty of memory to work with. However, after making some minor changes, suddenly I start getting errors which are repeatable, but completely nonsensical, and which prevent the data field from loading/running in the simulator. The only rational explanation seems to be some type of memory overflow/corruption. Even after refactoring some code and getting reported memory used *below* what was previously working, I was still getting the same bizarre behavior:

Memory used = 59160kb, free = 71896kb, total = 131072kb

After performing more extensive refactoring and reducing memory usage further I was eventually able to get the code to run once more. However, I'm wondering if anyone can help me understand why I'm having problems when it appears that I'm using less than 1/2 of the available memory?

Among other things, I'd like to understand this because I was hoping to port this data field to other devices. However, I'm thinking that may not be possible. For example, the Forerunner 920XT seemed like the logical next step, until I saw this:

<app id="watchface" memory_limit="65536" />
<app id="watch-app" memory_limit="65536" />
<app id="widget" memory_limit="65536" />
<app id="datafield" memory_limit="16384" />

Assuming these values are correct, then even converting my data field in to an application would be a waste of time. Can anyone confirm / refute that conclusion?

Thanks - David
  • Yes, the memory_limit values are exactly as you expect (the number of bytes available for an app of the given type). Given that you're nowhere near the memory limit, I doubt that is the problem. Ideally you'd get an exception describing the problem, but it sounds like you've got some sort of corruption (stack or heap) that is causing problems.

    I'm surprised you're able to write code to use up that much memory. Depending on what kinds of data structure you're using, you may be able to easily reduce the amount of memory you're using. It may be possible to drop it down enough that you'd be able to support some of the low memory devices like the fr920xt.

    Travis
  • The data you see in devices.xml is correct. The Epix is a bit different than other watches, as other devices with a 1.x VM (like the 920) have a 16k limit for DF's, while watches with a 2.x VM (like the 735) have a have of 26k max for DF's. (Edge/Oregon/Rino "handhelds" have larger "maxes" for DFs).

    So for other watches, you're data field has got to be 16k or 26k to run on anything other than an Epix

    To make things a bit more "interesting" the Epix is still running a 1.2.1 CIQ VM (which is quite old... Other devices are running 1.3 or 2.x VMs).

    While you may see plenty of memory for a DF on the Epix, you may be running out of objects. There's a limit of something like 256 objects, so that could actually be what you ran into. You may see an "out of objects" error instead of an "out of memory" error, but not sure with the Epix and if you're using an older SDK.

    (You didn't mention which SDK you're using, but I'd use 2.1.5 SDK and maybe the the 2.2.0 beta SDK as you might get more details on what's happening)

    update: Travis beat me by a few minutes, but to go with what he's saying, how you have your data structured could be using more memory and more objects than needed. For example, using multi dimention arrays will burn objects fast (and might show as "out of memory"). And even with one dimensional arrays, if you have one or two that's 10k, that alone might prevent running on other watches.
  • Yes, the memory_limit values are exactly as you expect (the number of bytes available for an app of the given type). Given that you're nowhere near the memory limit, I doubt that is the problem. Ideally you'd get an exception describing the problem, but it sounds like you've got some sort of corruption (stack or heap) that is causing problems.

    I'm surprised you're able to write code to use up that much memory. Depending on what kinds of data structure you're using, you may be able to easily reduce the amount of memory you're using. It may be possible to drop it down enough that you'd be able to support some of the low memory devices like the fr920xt.

    Travis


    I've formed a tentative conclusion based on which type of changes seemed to resolve the issue (and which ones don't seem to matter!) that Jim's reply (following yours) regarding a limit on the number of objects or something similar is what I'm running into. It seems that the number of global variables I'm using is critical. Here's an almost complete summary of the global constants (which don't seem to matter) and global variables (which do) I'm using showing data type and number of instances:

    const (boolean): 5
    const (float): 6
    const (int): 25
    const (string): 2
    const (array, 1-dimension): 3 (15 total integer elements)

    hidden var (boolean): 12
    hidden var (float): 19
    hidden var (int): 66
    hidden var (long): 8
    hidden var (string): 13
    hidden var (array, 1 dimension): 10 (28 total integer elements)
    hidden var (array, 1 dimension): 1 (6 boolean elements)
    hidden var (array, 1 dimension): 1 (8 float elements)
    hidden var (array, 1 dimension): 1 (8 string elements)

    "Previously on Hill Street Blues" (which won't mean anything if you're too young!) I was using a layout with about two dozen labels. For each label I declared a "hidden var objLabel01" variable to hold the object reference pointer which I looked up only once in the onLayout method, and then referenced in the onUpdate method as needed to display values, change their font/color/etc. I assumed that would be somewhat more efficient than making "findDrawableById" calls over and over again. However, I was only able to resolve my apparent memory corruption issue by completely eliminating the layout and all the related code, and using drawText calls instead.

    I'll add some additional information in a reply to Jim's message...
  • The data you see in devices.xml is correct. The Epix is a bit different than other watches, as other devices with a 1.x VM (like the 920) have a 16k limit for DF's, while watches with a 2.x VM (like the 735) have a have of 26k max for DF's. (Edge/Oregon/Rino "handhelds" have larger "maxes" for DFs).

    So for other watches, you're data field has got to be 16k or 26k to run on anything other than an Epix

    To make things a bit more "interesting" the Epix is still running a 1.2.1 CIQ VM (which is quite old... Other devices are running 1.3 or 2.x VMs).

    While you may see plenty of memory for a DF on the Epix, you may be running out of objects. There's a limit of something like 256 objects, so that could actually be what you ran into. You may see an "out of objects" error instead of an "out of memory" error, but not sure with the Epix and if you're using an older SDK.

    (You didn't mention which SDK you're using, but I'd use 2.1.5 SDK and maybe the the 2.2.0 beta SDK as you might get more details on what's happening)

    update: Travis beat me by a few minutes, but to go with what he's saying, how you have your data structured could be using more memory and more objects than needed. For example, using multi dimention arrays will burn objects fast (and might show as "out of memory"). And even with one dimensional arrays, if you have one or two that's 10k, that alone might prevent running on other watches.


    You'll get a sense of my global object usage in my reply to Travis' message, and I think that's the issue I'm running into since chopping out chunks of code doesn't seem to help - and heck - the reported memory usage is only about 1/2 of the presumed memory available for use! I'm using V1.2.11 of the SDK. Until about a week ago I was only trying to target the Epix for myself and a couple of friends, and following the "if it ain't broke don't fix it" approach - sticking with 1.2.11. We've been side-loading the PRG file, and since conventional settings weren't available for use, I implemented direct on-device configuration support by reading the user profile height and weight. After getting everything working well, I then went to add standard setting support. It was during this process that I suddenly starting getting errors which made no sense. Typically something like this:

    Failed invoking <symbol>
    Unexpected Type Error
    in SetControlColors (Z:\ConnectIQ\Eclipse_Workspace\AllSkate\source\AllSkateView.mc:1881)
    in SettingsHandler (Z:\ConnectIQ\Eclipse_Workspace\AllSkate\source\AllSkateView.mc:2619)
    in initialize (Z:\ConnectIQ\Eclipse_Workspace\AllSkate\source\AllSkateView.mc:528)
    in initialize (Z:\ConnectIQ\Eclipse_Workspace\AllSkate\source\AllSkateApp.mc:9)

    This being code that was working perfectly, and then suddenly wasn't. No changes were made to anything referenced on line 1881. It just felt like some type of memory corruption. I determined empirically that I was only able to resolve the problem by reducing the number of global variable declarations. It took a good bit of work, but eventually I succeeded, and have since submitted the app and am waiting approval. I don't really expect many users to be interested - my sense is there just aren't that many Epix users out there, and few of them will be interested in my data field. I figured a logical next step would be to support the 920XT which me thinks is a much more popular device. But my new found understanding (which is still quite limited!) of the memory issues makes me think that there's no way I'll be able to trim this code down enough to use less than half of the memory now in use.

    Having said that, can you give me a short pep talk on the implications of using a newer version of the SDK? I assume that I must do that to support the 920XT (or other newer devices) running current firmware. What is less clear is what happens to my ability to support my Epix device (which, as best as I can tell, is now dead-ended as far as any firmware updates are concerned)?

    Thanks - David