the watchdog is barking

Hey,

I am programming a datafield, which I wish to keep in datafield format, however there are memory and execution limitations which I am hitting, and I wanted to get some feedback concerning what you (all) thought was best practices...

1. I have divided some of the calculations up so that execution time isn't all packed into the Compute function, but some is also executed in the onUpdate function as well. This seems to be a good idea.

2?. Would anyone recommend utilizing a timer function to postpone execution for a partial second? ..for something which keeps going over the limit of executions, and causing the watchdog to crash the datafield (on the sim)

3. I have taken steps to minimize the creation of extra variables because they use a lot of memory, but it comes at the price of more calculations/executions, therefore that is another trade off I must consider. If I remove certain clarity variables, I have to add calculations/executions, which also cost memory, and increase the risk of alerting that damned Watchdog.

4. Another thing I have done is to transfer less-frequently-used variables into a single string variable and am using a function like the below one to access it. This accounts for some of my high execution rates - because this simple variable-checking function is heavy on usage, no doubt.
function getvar(x) {
return (myVariable.substring(x, x+1).equals("1") ? true : false );
}
//during Compute etc
if (getvar(2) ) { // not sure the "cost" of this operation
// do something...

As you can see, this function uses the .substring(x,y) and the .equals(y) method. Not sure how good it is compared to "==" or ">", etc other operators.

5. After having the Watchdog shut my simulated datafield down a number of times, I am now thinking more direct routes to checking variables is better, so now that previous check is simply a "if (xxx.substring" operation, I don't call that other function at all.

6. Since all variables are "objects", is there any preferred type of variable or operation which is preferred from a memory/execution-time standpoint? For instance, in C the documentation I have read indicates that shifting operations ">>" are quicker than traditional multiplication because they translate to binary shifting operations cleanly, whereas multiplication does not.

7. Another possible way to save memory, is to call "getProperty" function more often instead of creating a variable and loading the data at the beginning of program execution (as shown below).
if ( Application.getApp().getProperty("A").substring(6,7).equals("1") ) {
//playtone...
}

// alternative seems to create "copy" of the data, but is this way really ~better~ in terms of execution?
var earlyDeclaredVariable = myApp.getProperty("A").substring(6,7);
//.....
if (earlyDeclaredVariable == "1") {
//playtone...
}

so, is it a hefty price to call that "getProperty" function? (my program does require obtaining some data from settings). From the "View Active Memory" window it looks like I'm saving memory because instead of having three (what looks like copies!) of the data I only have two!!!




.....I have a few boolean data types, and some other floats and integers, however I was hoping I could figure a way to efficiently conduct this program, as a datafield. Is there an added benefit to using boolean data types, or maybe I should just stick with more qualitative variables so as to minimize unnecessary re-formating/organizing of data
.....I want to target as many Garmin watches as possible, and I believe it is possible, but I want to increase my memory and execution efficiency so that the user can use it more effectively... Right now I know a user can input about 8 points into my datafield, however I haven't tested the limits, and I was hoping to get a whole lot more, maybe like 30, if you know what I mean.
.....I've already got no variables in my onUpdate portion due to file exclusions, and it works across most Garmin platform (on the sim), so I'm happy for that.

.....Anyways, a bigger question is this: Is there any summary/information page which contains the memory and execution costs associated with each of these activities? Seems like such a page would be of great use to us "small-platform" programmers... I suppose I could program my own unit tests to discover more about this, but I was hoping there was some documentation or guidance available somewhere, that might be shareable... not to re-invent the wheel and all.
.....(my watch is a 630, so I have the added benefit of programming for the platform with one of the smallest memory footprints I think; I definitely want this datafield to work on my own watch!)
.....I have read somewhere in these forums that people have analyzed the .IQ file as a way to increase memory efficiency and program efficiency. I would be interested in hearing how one goes about this, although I would rather not have to break open the code to that extent, yet.


That watchdog is tough! :eek:
  • 1/ that's also what I do, some simple calculations I only need while drawing the field are done only during the draw to save memory.

    2/ that wouldn't be beneficial. It'd only consume more memory as you'd need another set of methods

    3/ Easy to recalculate vars I don't store in global variables, in my Peter's (Race) Pacer I went so far that I even don't store the heartrate zones during the initialize phase, but re-fetch the information every second during draw (I'm more limited in memory in this project than I am in processing power)

    4/ I don't think that's a good approach, string operations are costly.

    5/ get rid of your string operations

    6/ set up a unit test and find out.

    7/ that's an option to consider for me it all depends in how many methods you need the object and how the ratio memory/processing power to spare is for the specific project.
  • When splitting things between compute() and onUpdate() you want to be a bit careful and not do things in onUpdate() that are needed in compute(). compute() is called every second, even if the DF isn't on the data screen currently displayed, while onUpdate is only called if the DF is being displayed.

    As far as saving things as string in properties, you don't really save much memory, and use more CP time as you convert/extract things.

    To keep an eye on memory, the bottom line of the sim does show the idle memory usage/max that can be used, as well as peak, and you can display the current at points in your code with Sys.println() and usedMemory in Sys.Stats

    It sounds like the watchdog may be the biggest issue though. It triggers after "x" instructions are executed without returning to the VM (x is different on different devices) That often means you have to rethink the way you are doing something intense. Timers cant be used in a DF, so you can't just wake your DF up again 1/10th of a second after you leave compute(), for example.

    You may need to look at how you do things in general. For example, lets say you need the average of large number of values. You do not want to walk all the values and figure out the average each time compute() is called, but instead figure out the average as the data is added to the list of values, so when you add the 1001st value, you use the avg for the first 1000, and factor in the 1001st, with a small bit of code executed. You also want to avoid doing something like copying one large array to another. Basically, look at anything you do in a loop.