Simulator Fidelity

I understand the difficulty in providing good fidelity simulation with such an annoying plethora of devices but whether I can understand the difficulties or not the end result is still painful.  I have recently written code to download workouts from a third party site.  I re-invoke  the original web request method on failure reported in the callback.  Fine in the simulator.  Not allowed on the device.  Hours wasted.  I now realise I need to poll a state machine to do achieve what is needed with a timer invoked method.  But timers are not what they seem as they are not reliably garbage collected when stopped and no longer referenced.  It is a recipe for the too many timers error.  When these issues are added to the "error invoking <symbol>" with no stack trace and flaky in-line debugging developing becomes a pain.  These issues have been around for years now.  Do Garmin ever feel a little embarrassed about this underperformance when compared to the toolchain available for Watch or Wear OSs?

  • It depends on if you understand Monkey C or you don't.

    ? You mean to say that the truth of the statement "reference counting is a form of garbage collection" depends on whether I understand Monkey C? I get that Monkey C does reference counting. I'm just saying that "GC" has different meanings depending on the context.

    - One meaning of GC is all forms of automatic memory management, including reference counting

    - Another meaning (arguably the most common) is "tracing garbage collection" (as in having a separate "garbage collector" process)

    https://en.wikipedia.org/wiki/Tracing_garbage_collection

    Tracing garbage collection is the most common type of garbage collection – so much so that "garbage collection" often refers to tracing garbage collection, rather than other methods such as reference counting – and there are a large number of algorithms used in implementation.

    Here's one blog that mentions reference counting when discussing garbage-collected languages.

    https://www.lucidchart.com/techblog/2017/10/30/the-dangers-of-garbage-collected-languages/

    The novice programmer may be misled into believing garbage collection prevents all memory leaks, but this is not the case. Although garbage collection prevents many types of memory leaks, it doesn’t prevent all of them.

    In automatic reference counting systems, such as Perl or Objective-C, memory is leaked whenever there are cyclical references, since the reference count is never decremented to zero. The solution in these systems is to break the cycle by specifying that at least one of the references is a “weak” reference, which doesn’t prevent the object from getting garbage collected.

    Nonetheless, you're probably right that the OP meant "tracing garbage collection" based on context, so my comment was likely just splitting hairs / playing semantics / taking a cheap shot, and I sincerely apologize for that.

    There's probably also a conflation between "setting a timer" and allocating a Timer object here, hence the reference to garbage collection. Afaik you can create as many Timer objects as you want, the real issue is setting more than 3 timers simultaneously (with Timer.start()).

    Have you even worked in the underlayer of anything that does GC?  I have.

    Where did you get a comp sci degree?

    I really don't want to get into a credential/experience war and/or doxx myself. You win, man.

    All I'll say is I have a CS B.Sc. from a university with a good rep for CS, and I've worked with various OS's (custom embedded OS, Linux, Windows, macOS), lots of platforms (embedded, desktop and server) and lots of languages (C, C++, C#, Java, JavaScript, TypeScript, Scala, Python and more.) As far as application domains go, I've worked on server apps, desktop apps, web apps, kernel code, networking/protocol implementations, and more.

    None of that really matters because it doesn't prove one way or another that I know what I'm talking about, and it doesn't matter either way. For the purposes of this argument, let's just assume I don't know anything at all.

    Regardless of anything else, all I wanted to say was that I wish the simulator was closer to the actual devices, and that devs in the past have complained about this. I should've said it in a nicer way.

  • Also your design doesn't really need a bunch of timers.  What you want is a single timer, that controls the other functions.  Even advancing your state machine.

    Without knowing / understanding more about the OP's code, I tend to agree with this.

  • How patronising.  I have used it for years (and the inherent problems remain).  I have numerous successful applications on CIQ.  Of course I know Monkey C does not compile directly to code that will run on a device. The simulator requires the JVM so I presume Monkey C compiles to p-code and that this is ultimately compiled again to code that can.  This has no relevance to the points made!  I did not say I need "a bunch of timers", merely that I need a timer and a state machine to use Comm successfully.  Any chain of Comm requests with callbacks is vulnerable and if I cannot re-invoke a call (you can on the sim, you can't on a device) then I need a completely different architecture to achieve the task.  Despite the more modest ambitions of a simulator I would expect it to have the same tasking model.  This sim does not and therefore wastes time.  I certainly don't need a lecture on reference counting!  The problem with timers is that they persist for an indeterminate period of time with a reference count of zero so even if at some instant I have no references to any timers I can't safely create another if I have already created three as this is likely to produce the too many timers problem.  I can only switch off a timer and dereference it not destroy it.  Timers call object instance methods so as a result any object with a timer has to persist.  I can't create (and when finished zero reference them) on the fly as if I do I will get the timer error even if there are currently no referenced timer objects. This permanent use of memory is contrary to design principles on resource limited hardware and in this regard differs significantly from Watch and Wear OSs (both of which use reference counting but do not have this timer issue!).  If you have something sensible to say Jim I will listen.

  • Post code that demonstrates your issue, including things like SDK version, app type, etc.  Could this all be a result of your makeWebRequest?  Are you trying to use bulk download?  Android/iOS/Wifi?

  • Rather than having multiple timers, each of which invokes a single action, is it possible to have a queue of pending actions to be executed on timer expiration? That way you could potentially use a single timer for everything. This approach could be refined to only ever execute one pending action per timer expiration, if necessary.

    Apologies if I'm not understanding the use case / design here.

  • I never use more than one timer, and one timer handles everything, be that updating the display, doing Comm requests, displaying  a message for a time, etc.

  • One of the issues I detected was Garmin's Auth request which on success on the simulator returns 200 but returns 2 on a device! 2.  The Internet Assigned Numbers Authority describes 2XX were X is a placeholder for a digit and where X is not optional.  It illustrates how poor the documentation of Comm by Garmin is.  I note it includes example code with callbacks to functions that are not methods of an object instance.  Functions in Monkey C are not first-class.  Out of interest I had a quick look at the documentation of the mobile SDK.  It remains out of date (after years).  I know AGILE development reduces the emphasis on documentation but that is not the same as not documenting or incorrectly documenting.  As for using a single timer - yep - that is a work around (-;  I typically limit myself to no more than a couple of timers that persist during the lifetime of the application.  It's not great and of course if there is too much hanging on a timer it may time out. The Timer class should merely be a wrapper with the underlying timer being instantiated when started and deallocated when stopped by the OS.  Oh well, there is no equivalent ability to develop for any other truly sport focussed watch at present as the others are too battery hungry so I will just have to suck it up until something better comes along.

  • Are you sure you're seeing a "2" and not a "-2"?  "-2" has a specials meaning in CIQ.  BLE_HOST_TIMEOUT

  • Yes.  I thought that too but the value is (+)2 (and I think should be returning 200). I get a dictionary back in data with the code.  Everything else works like clockwork now.  I just have to accept 2 or 200 (so works on device and on the sim for development).  I think I have reported this problem before and just forgot it.  So did Garmin!