WatchFace settings and memory

Hi n

as usual, I try to save memory... I've learned many tech here.

So I have an other question,

I have a watchface with ring data,

you can either have bars (with dc) or curved font, option in the settings.

To save memory I do something like : 

if(App.getApp().getProperty("Num")){ fontC = WatchUi.loadResource(Rez.Fonts.Curved);}else{fontC=null;}

so that the font is not loaded if you don't use numbers in the ring.

my question is, is there any way to do the same thing but with functions?

I mean if someone chose "Numbers" option, all the "bars functions" are not loaded?

with a class?

I know the code is loaded even if I don't use it.

I hope I'm clear enought...

  • You can define what code is loaded at compile time, but not at run time.

  • Memory, memory, memory, always so close in our thoughts Slight smile

    Are you thinking of something like the following? For a single call I expect it is more expensive, but if you have a lot of optional resource loading and all your resources are listed within the same array in that function then maybe it could save some memory (you'd have to test …)

    using Toybox.WatchUi as watchUI;
    using Application.Properties as applicationProperties;
    
    function loadResourceIfProperty(propertyKey, testState, resourceIndex)
    {	
    	var fonts = Rez.Fonts;
    	var graphics = Graphics;
    
    	var resourceList = [
    			fonts.Curved,
    			fonts.somethingElse,
    			
    			graphics.FONT_SYSTEM_XTINY,
    			graphics.FONT_SYSTEM_NUMBER_HOT,			
    	];
    	
    	return ((applicationProperties.getProperty(propertyKey)==testState) ? watchUI.loadResource(resourceList[resourceIndex]) : null);
    }
    
    function testFunction()
    {
    	var curvedResource = loadResourceIfProperty("num", true, 0);
    }

  • Many thanks for this I use pretty the same things for the ressoures

    var LNG = Ui.loadResource(Rez.Strings.LANG).toNumber();
    
    var FONTs=[fonts.customFontSRUS,fonts.customFontSSLO,fonts.customFontSGRE,fonts.customFontS,fonts.customFontS];
    var CFS = Ui.loadResource(FONTs[LNG]);

    I think it pretty closed.

    So it was not about ressources but code and like what I though and like confirmed it is not possible,

    at least I saved memory for the one doesnt want number.

    In case it helps someone else to save memory, cause like you said "

    "Memory, memory, memory, always so close in our thoughts " ;)

    	function Settings(){
    		if(App.getApp().getProperty("Num")){RingData = [null,:DrawStatus,:DrawBattN,:drawStepsN,:drawDistN,:drawKalN,:drawFloorN,:drawHrN,:DrawBattStat,:DrawSEN,:drawAltN,:drawActMN,:drawHPA];}
            else {RingData = [null,:DrawStatus,:DrawBatt,:drawSteps,:drawDist,:drawKal,:drawFloor,:drawHr,:DrawBattStat,:DrawSE,null,null,null];}
    		if(App.getApp().getProperty("Num")){ fontC = WatchUi.loadResource(Rez.Fonts.Curved);}else{fontC=null;}
    	}
    	
    	
    	
    	function onUpdate(dc) {
    	(...)
    	    for(var i = 1;i<6;i=i+1){
    			var data = App.getApp().getProperty("R"+i);
    			if (data>0&&RingData[data]!=null){
    				var func = method(RingData[data]);
    				func.invoke(dc,i-1);
    			}
    		}
    	(...)
    	}

    for(var i = 1;i<6;i=i+1){ ...  6 because it concerned  5 data fields.

    have a great day and many thanks

  • Hi ! Here I am again, with an other question on memory !

    Stuck out tongue winking eyeI m quite new in monkey c,

    Before That I Only code with vba, 

    In vba, if I set a variable, At the end of the code, if I wa't to save memory, I have to set it to null (nothing)

    Shiuld we have to do the same thing here ?

    I guess it will save memory but not peak one ?

    Have a great day 

  • These are the things that I can remember learning about variables and memory:

    • All variables can store values up to 4 bytes without allocating extra memory. (A value of null still takes up 4 bytes)
    • Declaring a variable actually takes up more memory than those 4 bytes (20, 30 or so?)
    • Variables that point to longs, doubles or arrays have extra memory allocated (which gets freed up when nothing else references that memory - normally when that variable is freed or set to a different value like null)
    • Variables declared within a function only ever get freed up at the end of that function - so sometimes it can be useful to set them to null within the function, e.g. if you are allocating multiple temporary arrays and only using one or two at a time then this can reduce peak memory. Declaring a temporary variable or memory allocation within a bracket scope { } then it still won't be freed until the end of the function.
    • If you have a variable that references an array or resource and you assign it to a different array or resource then the original memory gets freed up (as it is no longer referenced). But I believe that temporarily both chunks of memory are allocated (potentially increasing peak memory) - setting the variable to null before assigning to the new array/resource can work around this.
    • Using a variable pointing to an array of values can work out cheaper memory wise than declaring multiple variables each with one value (because of the overhead per variable).
    • Using byte arrays can be even cheaper (if all your values are in the 0-255 range).
  • One thing to keep in mind with CIQ are objects, as it's not a flat memory allocation.  In CIQ there are simple objects and complex objects, with simple objects being Boolean, Floats and Numbers.  Things with a value that always fit in 32 bits.  

    And then there's complex objects - like Arrays and Doubles.

    consider these two things:

    var a=[1,2,3];

    var b=[1d,2d,3d];

    var a is a single object with 3 simple objects

    var b is 4 objects - the array with 3 complex objects

    You can see here that a is 30 bytes, while b, 78 (30+3*16):

  • Many thanks!

    "Declaring a variable actually takes up more memory than those 4 bytes (20, 30 or so?)"

    I don't get this, what do you mean?

  • oh great to know, hopefully, I only use simple array. (a)

    I guess it is the same for stored object.

    for exmple for weather I use an complexe array

    let say, OWMCurr{"temp"=>18, etc etc

    it would be better may be on receivedata to do

    var Data=new[4]

    Data[0] = data.temperature

    Data[1] = data.humidity

    etc

    where data.temp is the received data?

    ????

  • So I just tested and it is 12 bytes - maybe I was exaggerating Slight smile

    In the simulator I opened the memory view, then I added "var myTestVar;" to my view class, then I ran and checked the memory view again. And the difference in global size is 12 bytes - just for one uninitialized variable.

  • If you add code to copy the array, then you also have to take account of how much memory that code takes up! So it might be better or worse Slight smile

    I find myself checking the memory view, then try making a change, and then comparing the memory view afterwards to what it was before and see whether the change was a good or bad one.