For application developers, performance optimization on embedded hardware is always a challenge. QtQuick provides a free performance boost through QtQuickCompiler, which improves performance simply by enabling an option without changing the source code.
Regarding QtQuickCompiler, the R&D team has already conducted performance benchmarks, such as:
Nonetheless, I think those tests mainly concentrate on the QML language itself. As an application developer, my primary interest lies in gauging the potential improvements at the application level. Consequently, I chose the existing QtQuick Coffee Machine demo as the test subject and utilized the Colibri iMX6ULL hardware platform for testing.
I conducted tests using the following five cases:
QML_DISABLE_DISK_CACHE=true
.As of Qt 6.8, qmltc is still in the technical preview stage and has several limitations. For example, default QtQuickControls cannot be used directly in an application. (https://doc.qt.io/qt-6/qtqml-qml-type-compiler.html#known-limitations)
To address this, I created an experimental temporary solution using some CMake tricks: https://git.qt.io/se_japan_public/qtquickcontrolscompiler. This solution provides a wrapper function qt_add_qml_module_qmltc
for qt_add_qml_module
, which takes an additional QtQuickControls style parameter after the CMake target specification.
Example usage:
qt_add_qml_module_qmltc(apptestQtQuickControl Basic
URI testQtQuickControl
VERSION 1.0
QML_FILES
Main.qml
)
Since QtQuickControls styles are implemented in QML rather than C++, using qmltc
for an application that includes a Button from the Basic style results in an error like this:
Error: Main.qml:10:5: Can't compile the QML base type "Button" to C++ because it lives in "QtQuick.Controls.Basic" instead of the current file's "untitled" QML module. [compiler]
Button {
^^^^^^
Understanding this limitation, the solution involves feeding the required QML files to qmltc
for compilation. The qt_add_qml_module_qmltc
function's second parameter (e.g., Basic
) automatically locates and includes the corresponding style’s QML files, binding them to the specified CMake target. This effectively makes components like Button
available within the module. The required private libraries are also linked, though for now, only the Basic style is supported.
To conduct the benchmark, I added the following enhancements to the Coffee Machine demo:
Modified source code: https://git.qt.io/se_japan_public/qt5-qt6-benchmark/coffee-benchmark
The benchmark consists of two tests:
Here are the benchmark results of 100 iterations.
QtQuickCompiler | Boot time (ms) |
qmlcachegen | 428.04 |
qmlsc-direct | 425.25 |
qmlsc-static | 428.72 |
qmltc | 346.74 |
Off | 682.76 |
QtQuickCompiler | Average FPS | Frames | Running time(ms) |
qmlcachegen | 50.3352 | 25181 | 500266 |
qmlsc-direct | 50.4937 | 25260 | 500260 |
qmlsc-static | 50.4947 | 25261 | 500270 |
qmltc | 50.8467 | 25437 | 500268 |
Off | 50.3136 | 25170 | 500262 |
The performance of qmltc
is impressive, reducing QML load time by nearly half. However, as a reminder, qmltc
is still in the technical preview stage, so it should be used cautiously in production projects.
The different qmlsc
modes showed similar performance improvements.
In terms of FPS, qmltc
also had the best numerical result, though all cases showed only minor improvements. This aligns with my expectations because the Coffee Machine demo does not extensively use StackView
or Loader
for dynamic QML loading. the current result of FPS is more likes that it has already limited by hardware constraints.
The Coffee Machine demo is relatively simple, and a more complex application may demonstrate even greater improvements.