Strange Compute() Interval Observation

I always thought compute() was called once per second for most devices unless they were compute bound. I never tested it.

We're seeing in a compute intensive data field running on an old/slow EDGE 820 is not accumulating a value as quicky as it should. Other devices match the post-ride server calculations, but the 820 is about 20% too low. So it seemed (to me) like it was bogged down and I was betting compute() was being called about every 1.2 seconds on that device.

So I wrote a little metric to display on the screen in the bottom left, that displayed the interval time using "elapsedTime". I expected to see about 1.00 seconds on my EDGE 1030, and I expected to see about 1.20 on the EDGE 820. I use a simple approach of saving the prior elapsedTime inside the method I call from compute(), and calculating the difference in current elapsedTime and displaying the value/1000.0 (for seconds).

SURPRISE SURPRISE

In the simulator, it shows a steady 1.00.

On my EDGE 1030, that interval varies every second (onUpdate() display refresh interval) between about 0.25 and 1.3. So it seems to imply that compute() is being executed between every 1/4 sec and 1.3 secs.... Does that even make sense?

I'll recheck my code and also now capture an average interval value. But the code is very straight forward so I don't know why it should show an interval time less and 1.0.

  • What I‘ve seen with compute intensive datafields on Edge 1030:
    on running and recording activities, the timer does not show continuous counting seconds, but skips up to 3 seconds per 10 seconds: 1,3,4,5,7,8,0….

    Yeah I've seen skipped seconds too (for CIQ data fields, not sure about native fields), but like flocsy pointed out, it's important to determine whether onUpdate() or compute() is being skipped/delayed.

  • lol yeah I'm aware of the inverse mistake. good to remind people. anyway I did implement the average interval and my EDGE 1030 is 1.01. I'm curious what the 820 will show once we get them to try.

  • Well I set the interval variable based on entering compute(). so really the onUpdate cadence doesn't really matter... it'll show the most recent compute() interval regardless. And that was showing a variance from 0.25 to 1.3 seconds. That was totally unexpected to me. I assumed there was a hard interrupt in the device firmware that triggered compute() once a second (best case) unless something was really bogging down the CPU and delayed that trigger. The simulator does seem to implemented a 1 sec trigger. But at least on the EDGE 1030, that is highly variable.

  • 2 weeks ago I noticed on my watches that if you have a timer field next to them, then onUpdate is called very frequently in the 1st 10 seconds. I'm not sure about compute, but could be the same. The reason seems to be that the timer field displays the 1/10th of a second resolution (maybe "seemingly" even 1/100) in the first 10 seconds.

  • I'm not sure about compute, but could be the same.

    I hope not, as the documentation explicitly says compute() is called once per second. I could understand it if they really meant "an average of once per second" or "usually once per second", but allowing onUpdate() to be called 10 times per second for 10 seconds is clearly breaking that promise.

    Afaik, the documentation doesn't say anything about how often onUpdate() is called for data fields, except for this:

    [https://developer.garmin.com/connect-iq/connect-iq-basics/app-types/]

    Data Fields and Simple Data Fields

    The base class for data fields is WatchUi.DataField. This class extends WatchUi.View, and in many ways behaves similarly to other View objects. The View.onUpdate() method call will be made every time the data field needs to update.

    (Yes, I realize one could argue that the data field doesn't ever need to update more frequently than compute() is called, assuming it only ever displays data that's gathered or calculated in compute()....)

  • Yeah, but that's double not clear:

    1. The fact that a non CIQ field is added to the layout doesn't necessarily mean that the frequency of calling any function of the CIQ fields changes

    2. Even for the non CIQ timer field displaying the time with 1/10 or 1/100th second precision doesn't mean that much about compute. I mean it's an implementation detail. Maybe timer's (non CIQ) code doesn't even use compute, as all the calculation that needs to be done in onUpdate is formatting the string so it's done in onUpdate?

  • Yeah, but that's double not clear:

    1. The fact that a non CIQ field is added to the layout doesn't necessarily mean that the frequency of calling any function of the CIQ fields changes

    2. Even for the non CIQ timer field displaying the time with 1/10 or 1/100th second precision doesn't mean that much about compute. I mean it's an implementation detail. Maybe timer's (non CIQ) code doesn't even use compute, as all the calculation that needs to be done in onUpdate is formatting the string so it's done in onUpdate?

    Sure I agree with what you're saying. I only meant that for CIQ data fields:

    1) compute() is explicitly documented to be called once per second (so I sure hope it's never called multiple times per second, for a significant period of time)

    2) onUpdate() isn't guaranteed to be called at any given rate, other than "every time the data field needs to update". (Kind of a stark contrast from compute())

    3) From 1) and 2), one could infer that onUpdate() should be called at least once per second, and that there's no need to call it any more frequently. However, from what you've observed, it can be called more frequently. It think it's safe to say that this is the kind of implementation detail that Garmin doesn't want to document (and I don't blame them.) So I def understand why they wrote "every time the data fields needs to update". It's vague on purpose.

    Obviously if any of us assumed onUpdate() would be called no more than once per second in the past, that would be a mistake. (In general you can't rely on onUpdate() for calculations that span a time period anyway, as it isn't called when your data field is out of view.)

    Maybe timer's (non CIQ) code doesn't even use compute, as all the calculation that needs to be done in onUpdate is formatting the string so it's done in onUpdate?

    I don't think native fields necessarily do things the same way as CIQ, even for stuff as basic as computing the value and updating the display. For example, we all know that a CIQ data field can't update more than once per second *on demand*, although now we see it can happen in certain circumstances (outside of the control of the CIQ app.)

    Clearly there's something in the implementation that causes native fields to influence what happens in CIQ tho.