C

Memory optimization

You can reduce flash and RAM footprints by using one or more of the following optimization features or techniques:

Enabling resource compression

PNG compression

You can store an image with PNG compression by setting ImageFiles.MCU.resourceCompression. The image will be decompressed into the cache when needed. This reduces the size of the binary but adds decompression overhead. See ImageFiles.MCU.resourceCompression for more information about using PNG compression in Qt Quick Ultralite applications.

RLE compression

Unlike images that use ImageFiles.MCU.resourceCompression, RLE images with RGB888RLE, XRGB8888RLE, and ARGB888RLE pixel format, are decoded at runtime. This reduces memory usage considerably, but it does not support transforming (scale, rotate, shear, and perspective) such images.

See Lossless compressed image formats for more information.

Framebuffer size

You can optimize the framebuffer size by choosing lower color-depth and/or single buffering. See Framebuffer requirements for detailed information about the framebuffer size requirements.

You can also improve performance using the hardware layers if your platform supports it. See Improving performance using hardware layers for more information.

Font quality

The font.quality property allows more fine-grained optimization, by providing hints to render low-quality glyphs. You can set the font quality in QML to Font.QualityVeryLow, which saves memory consumed by those glyphs. See MCU.Config.defaultFontQuality for more information.

Omitting source language strings from translations

In some use cases, the source language strings of translations are not rendered at all. Especially when using ID-based translations, the application is not expected to display the source strings. Use the TranslationFiles.MCU.omitSourceLanguage QmlProject property to exclude the source strings from your application binary.

Monotype spark font engine memory optimizations

When the Monotype Spark font engine is used by setting MCU.Config.fontEngine to "Spark", there are some font engine specific memory optimizations that can be applied:

Remove unused glyphs from the font file

When using the Monotype Spark font engine with fontmap font files, it is possible to reduce the size of the font file using Monotype's FontmapEditor utility, which is shipped with Qt Quick Ultralite. This utility allows you to specify a unicode range for a font entry, and remove unused glyphs. This is useful when the subset of glyphs needed by the application is known ahead of time. Especially in the case of CJK font files, removing unused glyphs can result in significant size savings.

Refer to the documentation in the FontmapEditor for more details on how to use this feature.

Note: This feature is available in FontmapEditor version 3.1.1.

Placing Monotype data tables in external flash

When using the Monotype Spark font engine, several data tables used by the unicode and shaping engines get linked into the application. In total, these consume around 57 KB of flash memory.

Here is a list of the symbol names for the relevant data tables, including their size in bytes:

Data table symbol nameSize in bytes
decompositionData04440
decompositionData11562
decompositionData2200
decompositionData3940
decompositionIndex1664
msBidiIndex3286
msBidiLut3486
msBidiProps112
msMirroringOffset112
msDLPTrieData9814
msDLPTrieIndex4096
msGeneralPropsArray1056
msGeneralPropsIndex10268
msGeneralPropsLut13332
MsScriptRangesTable2680
Sum57048

Note: The MsScriptRangesTable is only included if MCU.Config.complexTextRendering is enabled, which is the case by default.

By customizing the linker script to place these data tables in external flash instead, it's possible to save this internal flash memory for code and other essential data.

To verify the data integrity of the Monotype data tables at the application startup, the bool Qul::validateMonotypeDataTableChecksums(Qul::Flags<MonotypeDataTable> tables) API can be used.

Below are examples of how to modify the linker scripts for the various supported toolchains:

GNU linker compatible linker script (.ld)

MonotypeDataTables :
{
    *(.rodata.decompositionData0)
    *(.rodata.decompositionData1)
    *(.rodata.decompositionData2)
    *(.rodata.decompositionData3)
    *(.rodata.decompositionIndex)
    *(.rodata.msBidiIndex)
    *(.rodata.msBidiLut)
    *(.rodata.msBidiProps)
    *(.rodata.msMirroringOffset)
    *(.rodata.msDLPTrieData)
    *(.rodata.msDLPTrieIndex)
    *(.rodata.msGeneralPropsArray)
    *(.rodata.msGeneralPropsIndex)
    *(.rodata.msGeneralPropsLut)
    *(.rodata.MsScriptRangesTable)
} > EXTERNAL_FLASH

IAR linker script (.icf)

"MonotypeDataTables":
place in EXTERNAL_FLASH {
    ro symbol decompositionData0,
    ro symbol decompositionData1,
    ro symbol decompositionData2,
    ro symbol decompositionData3,
    ro symbol decompositionIndex,
    ro symbol msBidiIndex,
    ro symbol msBidiLut,
    ro symbol msBidiProps,
    ro symbol msMirroringOffset,
    ro symbol msDLPTrieData,
    ro symbol msDLPTrieIndex,
    ro symbol msGeneralPropsArray,
    ro symbol msGeneralPropsIndex,
    ro symbol msGeneralPropsLut,
    ro symbol MsScriptRangesTable
};

GHS linker script (.ld)

As GHS does not support placing individual symbols, the entire .rodata sections from the files containing the data tables have to be placed in external flash:

.MonotypeDataTables :{
    // decompositionData0, decompositionData1,
    // decompositionData2, decompositionData3,
    // decompositionIndex
    "libQulMonotypeUnicode*.a"("*nfddat*.o")(.rodata)
    // msBidiIndex, msBidiLut, msBidiProps, msMirroringOffset
    "libQulMonotypeUnicode*.a"("*biddat*.o")(.rodata)
    // msDLPTrieData, msDLPTrieIndex
    "libQulMonotypeUnicode*.a"("*dlpdat*.o")(.rodata)
    // msGeneralPropsArray, msGeneralPropsIndex, msGeneralPropsLut
    "libQulMonotypeUnicode*.a"("*prp*.o")(.rodata)
    // MsScriptRangesTable
    "libQulWorldTypeSpark*.a"("*dat*.o")(.rodata)
} > EXTERNAL_FLASH

To verify that only the symbol names listed above (and their corresponding "TableSize" symbols) are placed in the .MonotypeDataTables section, examine the generated .map file.

Reduce the font cache size when using the text cache

When the text cache is used, there is less need to have a large font cache. The alpha maps for Text elements are, in any case, cached in the text cache. So the font cache isn't necessarily accessed every frame, only when new Text elements are shown or when text changes.

By setting MCU.Config.fontCacheSize, it's possible to reduce the font cache size substantially without any significant impact on performance.

MCU.Config {
    fontCacheSize: 16384 // reduce the font cache size when the text cache is enabled
}

In general, performance is increased by reducing the size of the font cache and letting the text cache have more memory instead. For details, see Text caching.

Reduce the application stack size

Based on profiling, the Qt for MCUs examples and demos do not use more than 11 kB of stack memory. The default stack size chosen is 24 kB to be on the safe side. By benchmarking the application and checking the value of QulPerf::maxStackUsage, some memory might be saved by reducing the stack size accordingly.

This optimization only applies to platforms where a fixed stack size is set in the linker script or to FreeRTOS, where the Qt Quick Ultralite thread stack size can be configured.

Available under certain Qt licenses.
Find out more.