Custom .iq package to reduce memory usage [Info No Longer Valid]

Folks, I sometimes read posts about crashes due to high memory usage, especially if your application supports a lot of devices..

I don't know if you're doing something like that or not, but as you know, memory usage is increasing with every supported device you added to your app. Good trick is to make a custom .iq package. I was on ~50 KB in development version of ActiFace 3.0, which I wanted to release with CIQ 1.2.0. It was due to higher CIQ VM memory consumption and due to new supported devices (230/630). Every new line of the code was shifting the app closer to the memory border and I wasn't able to add new features. That's the reason I decided to split ActiFace into several projects by screen shape, so now I have 4 :) (all with the same ID)



Of course, it brought necessity of merging of the new code into all clones (that's why I started using Git :) ), but I was able to clean and dramatically reduce the code for each screen type.

Now, I always build four .iq files and then create single one by copying all subfolders together (as you know, .iq file is just a ZIP), and merging manifest files into single one in the final package.




Now, I added a lot of a new code, added Tall support and I'm still on ~34 kB of memory usage. The biggest advantage is that each new device don't affect memory requirements.
  • If you make a drawable that requires a form-factor-specific implementation, then this is a useful trick. If you are using a layout (which consumes a bunch of memory), and have no form-factor specific code, there shouldn't be a problem. Right?
  • Right, my solution I posted is much more efficient if you're using device specific code constructions and the code is becoming too complex. Personally, I don't like layouts and I didn't find it very practical in dynamic faces as ActiFace. I think that similar problems have or had developers of Digic Watch or Analogical watchfaces. I like to have a full programmatic control over renderred elements.

    Otherwise, I realize that static faces can successfully use layouts to compile a slim code.
  • Interesting!

    But my reaction was that this could also be a way to increase memory - but I mean that in a good way!

    For example, watch-apps on the va, 23x, etc are limited to 64k, but can be 122k on the va-hr, and this would allow doing things to take advantage of the extra memory. Same with data fields. Older devices are have a 16k max but on the va-hr it's 26k. Add new features but only for devices that have the memory for it.

    (conditional compiles based on the target would be nice for this, but I have no idea if/when that might happen :( )
  • (conditional compiles based on the target would be nice for this, but I have no idea if/when that might happen :( )


    Absolutely, I hope and believe that we will be able to put source files into "target" folders in the same way as resources.

    My solution is just compilation of several apps and packaged into one. Some developers decided to have different apps on the store for different devices, but I'd like to have statistics and comments under single one, so I'm doing it in that way.
  • Petr - same here. I'd rather keep the devices together for the stats and reviews.

    I've been thinking of doing different versions based on something that might not be available on all devices (a baro or a hw compass for example), as while in the code I can figure out if it can be used, I'd just as soon not even have the code in the .prg for devices that don't have that feature. In that case with a "conditional compile", I could stay with the same source file, and on devices that have the feature, the code would be compiled in, and the others, the function could still exist, but do nothing.
  • This is a great solution which I for multiple applications also used.
  • Nice write up Petr,

    I am going to use this soon because of the curve ball that's been thrown to us in the form of the tall watch.

    Been dreading to update some of my watch faces because of this, but now have new hope.

    Just have to find time to do this. :(
  • Some issues with the merge...

    Hi Gents,

    I've been trying to apply this approach to port my Decoder watch face to the fenix 5 series on my mac without having to create a new watch face but with no success.

    I've created another project, use the same ID, merge the directories and updated the manifest.xml files, then zip and renamed to .iq but I'm having the following error when I try to update my project on the garmin site:
    The following errors were detected in your app file
    The uploaded file’s manifest.xml is not parsable. : MANIFEST.xml
    The uploaded file contains invalid paths. : Decoder/006-B2189-00/Decoder.prg, Decoder/006-B2432-00/006-B2432-00-settings.json, Decoder/006-B2604-00/Decoder_F5.prg, Decoder/006-B2547-00/Decoder.prg, __MACOSX/, Decoder/006-B2796-00/006-B2796-00-settings.json, Decoder/006-B2188-00/, Decoder/006-B2544-00/006-B2544-00-settings.json, Decoder/006-B2408-00/, Decoder/006-B2432-00/Decoder.prg, Decoder/006-B2467-00/Decoder.prg, Decoder/006-B2547-00/006-B2547-00-settings.json, __MACOSX/Decoder/, Decoder/006-B2408-00/006-B2408-00-settings.json, Decoder/006-B2697-00/006-B2697-00-settings.json, Decoder/006-B2413-00/Decoder.prg, Decoder/006-B2544-00/Decoder_F5.prg, Decoder/006-B2189-00/, Decoder/006-B2293-00/006-B2293-00-settings.json, Decoder/, Decoder/006-B2407-00/006-B2407-00-settings.json, Decoder/006-B2293-00/Decoder.prg, Decoder/006-B2188-00/Decoder.prg, Decoder/006-B2189-00/006-B2189-00-settings.json, Decoder/006-B2473-00/, Decoder/006-B2604-00/, Decoder/006-B2604-00/006-B2604-00-settings.json, Decoder/006-B2697-00/Decoder_F5.prg, Decoder/006-B2413-00/, Decoder/006-B2467-00/006-B2467-00-settings.json, Decoder/006-B2473-00/Decoder.prg, Decoder/006-B2797-00/006-B2797-00-settings.json, Decoder/006-B2408-00/Decoder.prg, Decoder/006-B2473-00/006-B2473-00-settings.json, Decoder/006-B2544-00/, Decoder/006-B2050-00/, Decoder/006-B2547-00/, Decoder/006-B2467-00/, Decoder/006-B2293-00/, Decoder/006-B2697-00/, Decoder/006-B2262-00/, Decoder/006-B2798-00/Decoder_F5.prg, Decoder/006-B2432-00/, Decoder/006-B2407-00/, Decoder/006-B2797-00/Decoder_F5.prg, Decoder/006-B2796-00/Decoder_F5.prg, Decoder/006-B2413-00/006-B2413-00-settings.json, Decoder/006-B2675-00/Decoder.prg, Decoder/006-B2050-00/Decoder.prg, Decoder/006-B2262-00/Decoder.prg, Decoder/006-B2797-00/, Decoder/006-B2407-00/Decoder.prg, Decoder/006-B2798-00/, Decoder/006-B2050-00/006-B2050-00-settings.json, Decoder/006-B2262-00/006-B2262-00-settings.json, Decoder/006-B2675-00/006-B2675-00-settings.json, Decoder/006-B2796-00/, Decoder/006-B2798-00/006-B2798-00-settings.json, Decoder/006-B2188-00/006-B2188-00-settings.json, Decoder/006-B2675-00/
    The uploaded file does not contain at least one 006-* folder.

    Does anybody have an idea on what I could be doing wrong?
  • You shouldn't need to do this any more. You should be able to use annotations or build file exclusion to compile out code that isn't relevant for devices. Build exclusions are covered in the programmer's guide here, and annotations are covered here.
  • There is also this thread by Travis where he gave some examples of annotations that I found very helpful.