App Settings always consume memory at runtime

Former Member
Former Member
My current project is a datafield, which has user configurable layout. The only way to transfer settings to the data field is to use application settings. In my case these settings are long configuration strings (concatenation result could be up to 1024 symbols long). During testing and debugging I noticed that these configuration strings are always present in used memory footprint and consume memory, which may result in of up to 1kb, which is very considerable especially for older devices with 16kb of memory per data field. Just for fun I tried to free this memory by using
App.getApp.setProperty(<property name>, ""), and strangely enough this worked and my app got 1kb more for the internal purposes until the end of its life cycle, but there was also a considerable setback: on the next app start I got empty values from these settings related properties.

Question is: does this functionality work as expected or is it possible to free memory used by settings values during runtime?
If this is how it was designed, then I would like to suggest an improvement at least for future SDK versions: let the developer to load settings values on demand and free memory afterwards, as even for 26kb data fields 1kb of memory is very considerable amount, which may be used for much better purposes. By the way, as there's no more description for deprecated function loadProperties in API docs, I can't be sure, but isn't my suggestion just a description of that deprecated behavior?

P.S. Simplified suggestion would be something like do not save property values related to application settings on application exit, this way developer would be able to free memory by assignment of empty strings or nulls.
  • I have noticed this as well. On a similar note, I have noticed that calling loadResource[] incurs a permanent one-time memory usage penalty which is proportional to the number of resources: about 36 + 40 + 12 * numberOfResources. It looks like if you don't call loadResource[], the array of resource Symbols is not kept in memory. If you do call loadResource[] any number of times, the array of resource Symbols stays in memory forever.

    For me that is about two hundred bytes which could be used for other things in the CIQ1 version of my simple data field. [I only use resources at initialization time].
  • P.S. Simplified suggestion would be something like do not save property values related to application settings on application exit, this way developer would be able to free memory by assignment of empty strings or nulls.


    The loads and saves are done behind the scenes, and the save is needed because there are cases where an app does change a property while running. While sometimes done with settings (the .set file), it's kind of the purpose of the Object Store (the .str file)


    when you did the setProperty to an empty string, that's something that an app may want to do and have the change saved for example. In the case of the .set, it seems to me that a save is done whenever a saveProperty is done. With the .str, it used to be that it was only saved when an app exits, but with background processes, I believe it is now saved on any change, at least on devices that support background processes, as that's one of the ways the main process can pass into to the background process.

    There's also the possibility that the user changes the .set by way of settings in GCM for an app, and the app is notified by way of onSettingsChanged(), meaning that even if the memory could be freed in some way, it would be used again if the user simply saved new settings.
  • Former Member
    Former Member over 8 years ago
    There's also the possibility that the user changes the .set by way of settings in GCM for an app, and the app is notified by way of onSettingsChanged(), meaning that even if the memory could be freed in some way, it would be used again if the user simply saved new settings.

    Well, I think I understand the difference between the object store and app settings, I even agree with the concept, that object store is updated only when app finishes without crash, but as the same API functions are used to access both store and settings it doesn't seem very logical that "settings related" properties can be modified by the watch app as well, because user can change these settings via GCM from mobile device or GE from PC. That's why I suggested imo one of the most obvious solution: do not write changes of the "settings related" properties to watch file system at the moment app is closed, I'm sure that it's not that hard for the OS to distinguish settings from object store properties according to the app settings definition.
  • There are cases where an app may change a setting, and I've done it in a few cases. One example is a read-only setting for a version number, etc
    I'd also guess that there are some apps that use the .set like the .str. Have a property without a setting.
  • IMO, none of that really explains why the symbol table for resources and actual values for properties have to be cached in RAM for the entire lifetime of the app. If certain properties or resources are only needed at init time, then it would be nice to get the memory back, even if it's "only" 200 bytes to 1kb. Setting a property to "", even if it worked as desired, sounds like a workaround for caching behaviour that some of us would like to be able to control in the first place.

    For example, there's initResources() and loadResource() (which I assume implicitly calls the former), but no freeResources() or unloadResource().

    To make an analogy with managed languages such as C#, (unmanaged) objects which aren't automatically freed by the garbage collector have a Dispose() method, so the programmer can decide when they are no longer using that resource. In C, you have malloc() and free(), open() and close(), etc.

    It would be really helpful to have that ability in this case.
  • I think the reason that it is cached is because disk operations are too slow to go out and fetch each time getProperty is called AND that monkey c really doesn't know that you only do the getProperty call from within the initialize function.

    This wasn't a real problem before as properties are typically very short as people need to enter them, but of course apps like your diy field [mis]use this ability to have user config by letting the user cut/paste text from a webapp.

    Having said that, I think you do have a point and as many of us only call getProperty only during the initialization function it might be worth - and maybe even easy - to add a optimization routine to the compiler [determine during pre-compile or second phase compile that the setting is not required after initialization] so that the resource can be freed after initialization has finished.

    I don't know whether same tactics could be applied for applications - such as most watch faces that have settings - which implement the onSettingsChanged function as each time that a property changes the properties would have to be refetched from disk which might induce unwanted lag/battery burn.
  • I think onSettingsChanged is kind of common - in watchfaces as well as other app types. I consistently use it for changing things in data fields, watch-apps and widgets too.

    Another thing that's likely common (last I looked, this is how things were done in the ObjectStore Sample), is that onSettingsChange isn't used, but in each call to onUpdate, the properties are read. A bit easier to code than onSettingChanged perhaps, but you are doing a more each time onUpdate is called.

    If this is a problem first/mainly hitting things like a data field on a 1.x device, I think the 1.x VM is pretty much maxed out in size right now, as they added as much 2.x functionality as they could to 1.x devices. Even if any kind of change is made, I think it's a safe bet that it would only be for 2.x devices, so it wouldn't do anything for 1.x devices.

    As Peter mentioned, I'm guessing in the majority of things, settings are maybe a short string or two, a few ints and a few booleans, so not really that big, and not really an issue.
  • In thinking about this, let's say you needed the memory in initialize for the setting, but then could free it. That would only help if you needed that extra memory for vars later on. The code space need would remain the same as when the setting was used, so you wouldn't have more memory for code.
  • Yes, that's a good point! But perhaps that assumes you are focusing on current memory consumption and not peak consumption. (I care more about peak consumption, because obv my app will crash if the peak goes too high, regardless of the average/best-case/typical-case consumption).

    Suppose a simple data field has a higher peak memory in the compute() phase than the initialize() phase. i.e. Let's suppose the amount of vars it uses during compute() is greater than during initialization (which is true for my app.)

    e.g.
    initialize: Peak 15.0k
    compute: Peak 15.2k

    Let's suppose I only use the resource table at init time, and let's suppose it uses 200 bytes of memory which can be magically freed after init, because Garmin backported that handy new feature to CIQ1.

    Now my numbers look like this:
    initialize: Peak 15.0k
    compute: Peak 15.0k

    I just got 200 bytes for "free", to use for anything I want, including code! If I add 200 bytes of code, now my numbers look like this:
    initialize: Peak 15.2k
    compute: Peak 15.2k

    Sure, my peak for initialize is higher, but I don't care. My app peak is still 15.2k, and I just added a new feature for CIQ1 devices.

    Same argument goes for properties. I really don't need any of those properties after init.