The QML Disk Cache¶
QML documents are pre-compiled ahead of time or cached after compilation at runtime.
To achieve optimal performance, QML documents are either pre-compiled ahead of time during the build process or cached after compilation at runtime. This page describes both strategies and how to configure the caching behavior.
Ahead-of-Time Compilation¶
You should define your QML modules using qt_add_qml_module that makes sure the Qt-Quick-Compiler processes your QML and JavaScript files ahead of time. This guarantees optimum performance at run time.
The Qt-Quick-Compiler generates byte code for each function and binding. This byte code can be used by the QML interpreter and the Just-in-Time (JIT) compiler in the QML engine. In addition, the Qt-Quick-Compiler generates native code for suitable functions and bindings. The native code is executed directly, which results in better performance than interpreting or just-in-time compiling byte code. Both byte code and native code are then compiled into your application binary.
One benefit of ahead-of-time compilation is that syntax errors in your QML documents are detected at application compile-time instead of at run-time when the file is loaded.
With CMake¶
When using CMake with qt_add_qml_module , QML files are automatically compiled ahead of time. You should load your QML documents from the resource file system where possible. This ensures the QML engine can find the code compiled ahead of time.
With qmake¶
When using qmake, you can enable ahead-of-time compilation by specifying CONFIG += qtquickcompiler in your project file. Qt Creator has a setting that allows passing this directive to the qmake command line. By default, it is enabled for release and profile builds.
When using qmake, you must organize your project in a specific way:
All QML documents (including JavaScript files) must be included as resources via Qt’s Resource system.
Your application must load the QML documents via the
qrc:///URL scheme.
Note that qmake cannot pass as much information to the Qt-Quick-Compiler as CMake. Therefore, the compilation will contain less native code.
Runtime Disk Caching¶
If no pre-compiled code is found at run time, or if the code cannot be used, the QML engine compiles QML documents into a byte code representation on the fly. Instead of re-compiling the same document each time it is loaded, the QML engine caches the compiled byte code. The caching process is automatic: each time you load a changed QML document, the cache is automatically re-created.
Cache File Format and Location¶
Cache files use the following extensions:
.qmlcfor compiled QML documents
.jscfor imported JavaScript files
.mjscfor ECMAScript modules
Cache files are located in a subdirectory named qmlcache of the system’s cache directory, as denoted by QStandardPaths::CacheLocation.
Memory Efficiency¶
Cache files are loaded via the mmap() system call on POSIX-compliant operating systems or CreateFileMapping() on Windows. This memory-mapping approach results in significant memory savings. In addition, when multiple applications use the same QML document, the memory needed for the code is shared between application processes, further reducing memory overhead.
Cache Validation¶
Cache files and ahead-of-time compiled code are only loaded if all of the following conditions are met:
The Qt version has not changed
The source code in the original file has not changed
The QML debugger is not running
Note that QML_FORCE_DISK_CACHE (see below) can override the QML debugger condition. The other environment variables do not influence these validation conditions.
Validation of ahead of time generated native code¶
The native code generated by the Qt-Quick-Compiler has some assumptions built in. If the conditions in which the code is executed differ from those in which it was compiled, the code may be unsafe to use. Therefore, the native code is validated at runtime using metadata stored alongside it. If this validation passes, the code is executed as normal. If it fails, the execution silently falls back to interpreting the bytecode instead. This validation happens once per file, the first time the code is loaded, and either approves or rejects all functions and bindings in that QML file as a whole.
You can customize the validation of AOT code:
To disable the validation at runtime, set the
QV4_SKIP_AOT_VALIDATIONenvironment variable. This allows you to avoid paying the small overhead of performing the validation.QV4_SKIP_AOT_VALIDATION=1 ./myQmlAppTo ensure that validation succeeds at runtime, set the
QV4_FAIL_ON_INVALID_AOTenvironment variable. If validation fails, the program is terminated. This allows you to make sure compiled functions are indeed executed as native code, for example.QV4_FAIL_ON_INVALID_AOT=1 ./myQmlAppTo disable the feature completely and prevent the Qt-Quick-Compiler from generating the metadata and validation logic, pass
NO_GENERATE_AOT_VALIDATIONto qt_add_qml_module .qt_add_qml_module(... NO_GENERATE_AOT_VALIDATION)
Configuration¶
You can fine-tune caching behavior using the environment variable QML_DISK_CACHE, which takes a comma-separated list of options. For example:
QML_DISK_CACHE=aot,qmlc-read
The available options are as follows:
Option
Description
aot-native
Load the compilation units compiled ahead of time and allow execution of any native code found in them.
aot-bytecode
Load the compilation units compiled ahead of time and allow interpretation and just-in-time compilation of byte code found in them.
aot
Shorthand for
aot-native,aot-bytecode.qmlc-read
Load any cached compilation units for QML and JavaScript files from the host file system and allow interpretation and just-in-time compilation of byte code found in them.
qmlc-write
When compiling a QML or JavaScript file on the fly, create a cache file afterward. The cache file can be loaded when the same document is requested again.
qmlc
Shorthand for
qmlc-read,qmlc-write.
Furthermore, you can use the following environment variables:
Environment Variable
Description
QML_DISABLE_DISK_CACHEDisables the disk cache and forces re-compilation from source for all QML and JavaScript files.
QML_DISABLE_DISK_CACHEoverridesQML_DISK_CACHE.
QML_FORCE_DISK_CACHEEnables the disk cache even when debugging QML. You cannot use the JavaScript debugger this way. It may fail to stop at breakpoints, for example. You can still use the QML inspector to explore the object hierarchy, though.
QML_FORCE_DISK_CACHEoverridesQML_DISABLE_DISK_CACHEandQML_DISK_CACHE.
QML_DISK_CACHE_PATHSpecifies a custom location where the cache files shall be stored instead of using the default location.