Acknowledged

Loading/unloading large json resources leads to VM crash over time

I find that there is a problem upon loading largish JSON resources over time in a widget causing the watch to reboot and the simulator to exit. This is easily reproducible on both the watch and the simulator (in the case of the simulator the simulator just hangs and crashes). In the simulator or the actual watch (fenix 7 sapphire solar) no debug messages are produced. On the watch the error log is provided at the end.
Investigation is pointing towards some garbage collector/caching/overflow issue on the VM. The widget that reproduces this issue nominally uses json resources and loads and unloads them as the user conducts searches as the total data to search in json is too large to be loaded once (so the json data is split in about 200 json resources to stay below the 255 maximum json ids). The json resource data is a simple dictionary with strings and arrays but of largish size. The watch memory monitor on the simulator shows that the Application.loadResource and then setting the variable holding the loaded dictionary to null works as expected (meaning the memory increases after the load and then decreases upon setting to null) and there does not seem to be memory leaks (the memory after release goes back in the simulator to the same value). However, after loading and unloading multiple times the watch crashes on the call to Application.loadResource even though the memory and peak memory reported is well below the maximum (peak memory is 562kByte for the worst load on fenix 7). It seems that the crash is linked to the amount of data being loaded over time regardless of the holding variable being set to null or which set of json resource have been loaded and unloaded. The number of loads before crashing varies depending on the total number of bytes loaded which seems to be around 640kbytes on fenix 7. This means for example that loading and unloading 10 time a JSON resource of 64kBytes will crash on the 10th time and loading/unloading 60 times a 12kBytes will crash on the 60th time.
This limits how long a user can interact with the widget, not factoring the inconvenience of having the watch reboot if they interact too many times.
If the json resource remains small (below kByte) there does not seem to be a limit.
The code stub for the function that does the load/unload is as follows:
typedef JsonResourceType as Numeric or String or Array<JsonResourceType> or Dictionary<String, JsonResourceType>;
//select json resource symbol to load upon user entry
DictionarySymbol  = null;
if (UserEntry == 0) {
      DictionarySymbol = :MyJsonResource_0;
}
else if (UserEntry == 1) {
      DictionarySymbol = :MyJsonResource_1;
}
else if (UserEntry == 2) {
      DictionarySymbol = :MyJsonResource_2;
}
...
//free memory from prior loaded data
Dictionary = null;
if (DictionarySymbol != null) {
    //Load new data
    Dictionary = Application.loadResource($.Rez.JsonData[(DictionarySymbol]) as Dictionary<String, JsonResourceType>;
}
error load on a physical device
3906 (fenix 7) SW ver: 1128
Build Type: RELEASE
Commit:27860a2152c7c765e210851d41cdcfa20dccd54b
ESN: 3435646052
04/14/23 12:42:50
RTL
errnum: 0x034
r0: 0x303cc7bb
r1: 0x00000000
r2: 0x00000054
r3: 0x303cc7bb
r4: 0x00000005
r5: 0x00000000
r6: 0x3819aaa8
r7: 0x00000000
r8: 0x303cc840
r9: 0x00000007
r10: 0x0000000b
r11: 0x00000074
r12: 0x00000004
r13: 0x303cc790
r14: 0x18b04fe5
r15: 0x18b05006
r16: 0x61100000
r17: 0x40000000
r18: 0x01000000
r19: 0xe000ed38
r20: 0xe000ed34
r21: 0x00000000
r22: 0x303cc728
Stack frame PC, SP: 0x100015f1, 0x3043b570
Call Stack - SP at 0x3043b570:
	0x10000805
	0x10000593
	0x18b04fe5
	0x100252a1
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x1000000f
	0x10000007
	0x1000000f
	0x1000000f
Uptime: 12412798
  • Thank you for the update. This is great news.

  • We have identified the issue and working on a fix.

  • the app is found at https://apps.garmin.com/en-US/apps/246024c0-f85d-45cd-aa8f-a77550108d44

    Nominally, for each letter the widget will load a json resource and free the prior dictionary. Adding letters reduces the need to swap json files as it narrows down the words so the best way to reproduce consistently is to select one letter and then remove it (using the back button) and select another and so on. starting at letter "a" with this test sequence it tends to crash around letter p or so. Starting form any other letter will usually crash after roughly the same number of letter but it really depends on the total size of the json loaded. Each json file is roughly 50kbytes although as you can imagine some letters are smaller (for example if you keep doing letters x, y and z it will go a lot longer before crashing as the relevant json are less than 50kbytes). This crashes on both the simulator and the physical device (not an IQ! crash but a hard VM crash). Let me know if more info is needed.

  • Hi 

    Can you point out which app is causing the issue, or if you can post a sample app? or prg

    Anshul

  • Thanks for this interesting thought. It makes a lot of sense. With this in mind, I tried to clear existing objects or not create any new objects/ new assignments in between loads to try to avoid new object being allocated to the heap after the json storage before loading a new one. This did not change the behavior so if there is fragmentation I have not found a way to control it well. It may be that as onupdate is called in between loads the fragmentation occurs through the graphics native calls. Any thoughts on what to try?