Suunto app Forum Suunto Community Forum
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    # What is the resource budget for a SuuntoPlus app, and what should we do when the firmware unloads one?

    Scheduled Pinned Locked Moved Suunto Plus Development
    2 Posts 1 Posters 131 Views 1 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • omunozO Offline
      omunoz Silver Members
      last edited by omunoz

      Suunto Race 2, FW 2.56.18. SuuntoPlus Editor v1.42.0.

      I am building a type: "device" sports app that holds a BLE GATT link to a companion phone app.
      It works well on its own. What I cannot get right is coexisting with the rest of the watch, and
      after a lot of log reading I do not think I can solve it without knowing numbers that are not
      published anywhere.

      What happens

      The failure scales exactly with the number of enabled apps. One session, one exercise:

      enabled apps result
      1 (mine) fine, indefinitely
      2 (mine + a Store app) fine, survives repeated screen switching
      3 (the documented maximum) my app is unloaded on the second round of screen switching
      14:14:37 : EVT APPLICATION : Zapp <app2>:Enable          <- second app
      14:15:14 : EVT APPLICATION : Zapp <app3>:Enable          <- third app
      14:15:21 : EVT APPLICATION : Zapp <mine>:templ load ...  <- switching screens
      14:15:33 : EVT APPLICATION : Zapp <app2>:templ load ...
      14:15:34 : EVT APPLICATION : Zapp <app3>:templ load ...
      14:15:36 : TRC MAPS        : Maps closed
      14:15:36 : EVT APPLICATION : Zapp <app3>:templ load ...
      14:15:36 : ERR APPLICATION : Zapp:relMemCb (exec:ui)
      14:15:36 : EVT APPLICATION : Zapp <mine>:Disable
      14:15:36 : ERR APPLICATION : Zapp 3:RelMem->unload
      14:15:36 : ERR BLE         : Ble:conn id not found
      

      The BLE disconnect on unload is documented and expected. The problem is that Zapp <mine>:Enable
      never appears again, so the connection cannot be rebuilt and the app is dead for the rest of the
      exercise — with no message to the user. Note also that the app the firmware unloaded is not the
      one that was churning: the third app mounted its template five times in twenty seconds.

      A pool the firmware itself reports as full

      At exercise start, with only my app enabled and before any of the above:

      14:12:54 : WRN WBMAIN : pool id:0 full! (S 140/140)
      14:12:54 : ERR WBMAIN : (0) Removed 121 non critical - size now=47
      14:12:55 : WRN WBMAIN : pool id:0 full! (S 140/140)
      14:12:55 : ERR WBMAIN : (0) Removed 117 non critical - size now=31
      

      140 slots, full, twice, with one app running. I do not know what pool 0 is or whether it is
      related to the eviction, and I cannot find it documented anywhere — but it is the only hard
      number the system gives me about its own limits.

      It does not look like my footprint

      Measured on the built blob — resident minified main.js plus the single mounted template:

      resident main.js 5 986 B
      largest template (compiled .xml) 6 379 B
      total 12.4 KB

      Over one day I cut my UI from 13 757 B to 8 666 B and reduced my module-scope function count from
      32 to 19. The behaviour did not change at all. I am clearly optimising against a number I
      cannot see, and I would like to stop guessing.

      What the documentation does not say

      The reference bundled with Editor v1.42.0 (6 March 2026) does not mention memory anywhere. It
      documents the API surface well, but there is nothing on:

      • how much of anything an app may use, or what the pools even are;
      • what counts against them — the mounted template, JS loaded with evalFile, subscriptions,
        manifest outputs;
      • which patterns are safe to use continuously and which are not;
      • what an app should do when the firmware takes resources back.

      FW 2.50.26 (7 January 2026) lists “Number of SuuntoPlus apps in sport mode increased from two to
      three”
      . So three concurrent apps is a shipped, advertised feature — but there is no guidance
      anywhere on the budget that makes three apps work, and I am seeing failures with one.

      Questions

      1. Is there a resource budget we should be building to? Even rough figures would change how we
        work: what the pools are, roughly how large, and what counts against each. What is
        pool id:0 (140 slots), and what fills it?

      2. Does the map view compete with SuuntoPlus apps for the same pool? Every eviction in my logs
        is adjacent to a map open/close. The map has grown a lot recently (contour lines, elevation
        labels, place names, road and peak labels), and the style loaded here is 4 792 B / 75 layers.

      3. How does the firmware choose which app to unload, and can an app influence it? A device
        app holding a live connection loses more than a screen when it is unloaded.

      4. What is an app supposed to do after RelMem->unload? Is there a supported way to be
        re-enabled within the same exercise, or should we treat an eviction as terminal and design for
        it? Right now I cannot even tell the user what happened.

      5. Is Zapp X:Disable without a following JS discard expected to release the app’s JS
        context?
        This matters a lot: if it does not, every eviction permanently costs shared heap and
        the situation degrades across a session rather than staying constant.

      6. Are there recommended practices for the UI side? Specifically: driving a high-rate value
        from a template — is $.subscribe in onActivate safe across repeated template mounts, or
        should <eval> with a script formatter always be preferred? Both appear in the docs; only one
        of them survived my testing, and I found that out from watch logs rather than from the manual.

      What would help most

      A short “resource budget and recommended practices” section in the reference. Not internals — just
      the numbers to build to and the patterns to avoid. Right now every developer rediscovers the same
      limits one freeze at a time, and we cannot tell a platform limit from a bug in our own code.

      Happy to provide full logs, the built blob, or a minimal reproduction if that is useful.

      Watches: SV Fw: 2.50.28
      SR2 Fw: 2.56.18
      IPhone 17 IOS 26.6
      macOS Tahoe 26.6.1 M1 & M2
      Apps IOS: 3.13.0 (23154)

      omunozO 1 Reply Last reply Reply Quote 0
      • omunozO Offline
        omunoz Silver Members @omunoz
        last edited by

        Follow-up: I ran the test, and I can answer my own question 5. The eviction path does not
        release the app’s JS context, and the shared heap is exhausted inside a single four-minute
        exercise.

        Method: fresh reboot, one exercise, three apps enabled, triggering the eviction repeatedly by
        switching screens and opening/closing the map. After each eviction I re-enabled my app from the
        SuuntoPlus menu without ending the exercise.

        Four evictions in four minutes

        # time how long my app survived after being enabled
        1 14:48:40 118 s
        2 14:49:07 14 s
        3 14:49:57 33 s
        4 14:50:27 15 s

        118 s the first time, 21 s on average afterwards — an 87% collapse.

        The heap is at 99.5%

        Two lines from the firmware itself, 16 seconds before the first eviction:

        14:48:24 : WRN UI_FRAMEWORK : JsTotMem 129980/133120   (97.6%)
        14:48:29 : WRN UI_FRAMEWORK : JsTotMem 132412/133120   (99.5%)
        

        This is the only figure the system has ever given me about its own limits, and it is not
        documented anywhere. An earlier report on this forum (topic 15490) describes the watch freezing
        at essentially this same level.

        Nothing is ever released

        None of the four evictions is followed by JS discard. The first and only one in the whole
        session appears at 14:50:35, when I stop the exercise. So every
        Disable → Load script → Enable cycle instantiates the module scope again while the previous
        one is still held.

        That also reframes the “three apps” case. It is not that a third app is too big — my own
        footprint is 12.4 KB, resident main.js plus the single mounted template. It is that three apps
        cycling through evictions exhaust a shared pool that nothing empties until the exercise ends.

        One caveat on reading this

        The intervals between evictions look almost constant (27, 50, 30 s). That number measures how
        fast I re-enabled the app by hand, not the watch. Survival time is the honest metric.

        And the last three survival times being similar does not mean it stabilised — it means the pool
        was already full before I started measuring. At 99.5%, any re-enable trips the release callback
        almost immediately.

        So, concretely

        1. Is Zapp X:Disable without a following JS discard expected to leak the module scope? If
          yes, a firmware eviction is not a recoverable event — it permanently consumes shared heap, and
          the watch degrades within a single session.
        2. Is there a supported way to make an app release its context on eviction, or to be
          re-enabled cleanly within the same exercise?
        3. What is the intended budget per app against the 133 120 B shared heap when three apps are
          enabled, which is the configuration FW 2.50.26 added?

        I have the full logs and the built blob available if that helps, and I am happy to run any test
        you would like measured.

        Watches: SV Fw: 2.50.28
        SR2 Fw: 2.56.18
        IPhone 17 IOS 26.6
        macOS Tahoe 26.6.1 M1 & M2
        Apps IOS: 3.13.0 (23154)

        1 Reply Last reply Reply Quote 0

        Hello! It looks like you're interested in this conversation, but you don't have an account yet.

        Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

        With your input, this post could be even better 💗

        Register Login
        • First post
          Last post

        Suunto Terms | Privacy Policy