Complete

This is by design.

The settings are being serialized to send to the simulator or phone.

opening settings editor consumes app memory

sdk 4.0.7
eclipse CIQ plug in: 4.1.0.beta1
eclipse ver: 2021-09 (4.21.0) Build id: 20210910-1417
windows 10
watch face
minSdkVersion 2.4.0

CASE 1

wf starts, peak memory 88.0

[ecilpse][app settings editor] - open only window and choose project (no push any buttons), peak memory 90.0

CASE 2

wf starts, peak memory 88.0

[simulator][property data]  - open only window (no push any buttons), peak memory 90.0

In both cases there is no calls for app.onSettingsChanged, settings data exist in memory so there shouldn't additional memory consumption.

Now, when you have e.g. 90.5 kB used from 92 there is an error "unable to serialise data" or "out of memory exception" if i choose OK in setting editor.

  • "or symbol should have constructor from string_number"

    Yeah, the inability to convert from a symbol to a number is a separate issue which isn't directly related to what I was talking about.

    I get that you don't like to have another array of symbols because it wastes memory but there's not much that can be done about that, either. I think the idea is that the dev is not supposed to know about the implementation details of Symbol, just the fact that it's a "lightweight unique identifier".

  • This is why sometimes it's cheaper to hardcode strings rather than putting them in the resource table - it all depends on whether the size of the resource table (the symbols, not the contents) is larger than the size of your hardcoded strings. If you have a small number of short hardcoded strings, and a large number of app settings strings, then it could be the case that the resource table would waste more memory.

  • "I don't agree  because as you noticed, when you load one string all strings are loaded. why? by design... probably"

    No, when you load one resource, the whole *resource table* (Rez) is loaded permanently. This doesn't load all the strings. If it did, then there would be no memory savings at all by using resources. But there's significant memory savings (assuming your app uses all the resources), because they don't all have to be loaded at once.

    The problem is that the resource *table* is loaded all the time, and it contains all the entries for app setting strings and fit contributor strings, which the app does not need.

    So say you have 50 strings for app settings, that's 50 x 12 = 600 wasted bytes. It doesn't matter how short or long those strings are, it will always be 600 bytes. Even 100 bytes is a lot for a Garmin app.

  • "But I'm almost sure that more number of  strings = more memory need (more members)."

    Yes that's what I said. But I also said that the *contents* of the strings don't matter. Rez.strings has resource IDs/symbols, not actual strings.

    You can test this easily by creating two strings in your resources, each 10 chars long, and calling loadResource() once (on one of the strings).

    Now change the *other* string to be much longer (like 255 chars) and run your code again. You will see that the peak memory will remain unchanged (as well as the memory taken up by Rez/Strings.

    Just now I tried a similar test with one of my apps, which calls loadResource() at least once:

    - Change one string (not loaded by the app) to be a lot longer: memory usage does not increase by a single byte

    - Add one string: total memory usage increases (global memory usage increases by exactly 12 bytes). 12 bytes per string is *huge*, especially for devices with only 16 KB or 32 KB of RAM for a data field.

    Why do I care? It goes back to strings that are only used for application settings. If my app calls loadResource() at least once, then every string I add (even if it's just for app settings) wastes memory. But at least it doesn't matter how long the strings are.

    It also means that I can store certain kinds of data as a very long string resource to try and save memory (although this kind of trick is only useful in very limited circumstances, like for old devices where JSON resources are unavailable and when the data that's being stored is only needed at init time, as opposed to all the time.)

  • I don't agree Slight smile because as you noticed, when you load one string all strings are loaded. why? by design... probably:

    BUILD: globals/Rez/Strings:
    BUILD:   CLASSDEF
    BUILD:     APPTYPE 127
    BUILD:     MODULEID globals/Rez/Strings
    BUILD:     PARENT globals/Rez

    1. each string has id_string

    2. compiler change id_string to symbol

    3. compiler build class Rez and inside another Strings/Fonts.etc Class String has members, each member is one id_string 

    4. when you load string system create object new Strings and loads all strings to the memory assuming that strings will be used many times, unlike, for example, fonts.

    But it doesn't matter, maybe I'm wrong (because you can't read strings during lowpower what suggest you are right)  But I'm almost sure that more number of  strings = more memory need (more members).

    If you have string not connected with context e.g. rez.string.name_of_steps there is no problem. But if you have string for days, months etc that are connected with numbers (JAN=1, FEB=2...) you have to read separately to array of rez... What about when you want to prints numbers in words?

    The problems is in ID that should be numbers:

    id=800 JAN

    id=801 FEB

    loadstring(currentmonth+800)

    simple...

    or symbol should have constructor from string_number

    id="800" JAN

    id="801" FEB

    for(i=0; i<11; i++)

    {

    months[i] = loadstring(new symbol((i+800).toString())

    }

    simple...