Watchface onPartialUpdate powerBudgetExceeded - with no screen updates!

I am maintaining the open-source Infocal watchface, and i am not able to get onPartialUpdate to work properly.

Even without any screen writes; GraphicsTime is showing 1,770,000 uS (1.7 seconds)!

Has anyone seen this before? What even is GraphicsTime when you are not doing any screen drawing Shrug tone1

This happens in Simulator, and on-Device (so at least they are consistent Slight smile

You can find my Watchface code here if you want to play around: 

https://github.com/blueacorn/Infocal

Thanks in advance,

Jay :)

  • Understand that onPartialUpdate will only be called by the system on MIP devices in low power mode.  In high power, the full screen is updated every second.

    Something very odd is happening in your code.  Did things work with the initial code you got from github?  It could be you started with a bogus app.

  • You are making expensive calls to Application.Properties.getValue() in onPartialUpdate(). 

    If you remove those calls, you will find that the watchface diags make more sense.

    Instead of reading properties continuously, cache them in the app, and use AppBase.onSettingsChanged() to detect when the user changes settings (via Connect or Garmin Express), at which point you can re-read properties.

    Yes, I realize that, hypothetically, application properties should already be cached in memory, even with the newer Application.Properties API, but I don't think you can argue with screenshot below.

    I def see application settings in the memory viewer, but at the same time it's possible that Application.Properties reads and writes from "disk" / non-volatile storage / flash anyway. I think it has been stated in the forums before that this is definitely the case.

    EDIT: the properties are cached in memory, but I think that's just to support the old, deprecated API. It seems that the new API doesn't use the cache at all. 



  • Did things work with the initial code you got from github?  It could be you started with a bogus app.

    The original app used the deprecated AppBase.getProperty() API call which is known to use the in-memory copy of properties instead of accessing the "disk" / non-volatile storage / flash.

  • Did things work with the initial code you got from github? 

    He didn't just get the code from github, he is also *maintaining* a fork of the original project on github. Meaning he branched off from the original project (that was shared with everyone on github), and now he's sharing his own version of the project (with everyone).

    It's github all the way down.

    Also worth noting that the original app is in the CIQ store with 100K+ downloads but the original dev has apparently abandoned it.

    But by sharing it on github, the original dev allowed the app to live on.

    Ofc nobody is forcing you, me or anyone else to share anything on github. But I'm just trying to point out that github is a lot more than a place to download bad code.

  • Yep, the original author "RyanDam" did an incredible job -- it looks like the code goes all the way back to CIQ1 - and they created hundreds of fonts to support anti-aliased rotating text, and anti-aliased analog hour/minutes watch hands for different screen resolutions! I have no idea *how* they created the watch hands fonts - it's a marvel!

  • Thank you for your assistance :)

    I was aware the Property reads needed caching - it was on the 'todo' list :) 

    I did not imagine it could cause this weird side-effect!  There's no way a property read takes 1.7seconds... is there ??!

    I assume it is throwing off whatever is used to do the Graphics time estimation. (note the partial updates ran <1s and there was no noticeable drain on battery when they ran, AFAIU)

    If Properties.xxxValue() are really that expensive, that would be ... _no words_!

  • You should never do anything that requires file system access in onParialUpdate.  I seem to recall at one point this was flagged as at least a warning, as file system access is expensive.

  • If Properties.xxxValue() are really that expensive, that would be ... _no words_!

    Reading and writing to non-volatile storage is going to be at least an order of magnitude slower than accessing volatile memory.

    Even the fastest NVRAM SSDs are roughly 5X slower than the fastest RAM chips. I'm sure the performance gap is much wider the parts that Garmin uses. 

    (note the partial updates ran <1s and there was no noticeable drain on battery when they ran, AFAIU)

    If you mean the new code with Application.Properties, how were the partial updates running if the power budget was exceeded?

    If you mean the old code with AppBase.get/setProperty, the explanation is that the old API uses the memory cache ("application settings" in the memory viewer) and only reads/writes to disk at the start/stop of the app.

    I def see application settings in the memory viewer

    Speaking of this, I thought about it for a second and realized the properties still have to be in memory in order to support the deprecated AppBase.getProperty/setProperty API. So there's a logical explanation for seeing app settings/properties in the memory viewer, yet also seeing the behaviour where Application.Properties reads or writes from disk and not memory.

    Silly me.

    Ironically, if those functions were actually removed for newer devices that aren't supposed to use them, many apps would see some memory savings. 

  • I am more than likely introducing my own bugs :) Although in my defence, I'm finding some of the Connect IQ VM behavior (like this one) somewhat suspect - and hopefully fixing more bugs than I add Fingers crossed

  • I recall when this started there was one exception to doing file system access in onPartialUpdate - being able to do something like System.println() calls for debugging.

    Search the bug report forum for "settings groups"