How it works...

This is similar to what we did in the previous example project that uses C++ and widgets except, this time, it is being automatically analyzed by the QML Profiler tool that's provided by Qt 5.

The QML Profiler not only produces the total time used for running a specific process, but it also displays the memory allocation, the execution timeline of your application, and other information that gives you insight into the performance of your software.

By looking at the data that was analyzed by the QML Profiler, you will be able to find out which part of your code slows down the program, allowing you to fix any problems quickly.

There are some rules that you need to be aware of when writing QML to avoid performance bottlenecks. For instance, type conversion can sometimes be expensive, especially between types that are not closely matched (string to number, for example). Small issues like this will likely snowball into bottlenecks when your project grows larger over time.

Other than that, try not to use id for an item lookup multiple times in the block of code that is being run often, as in the following example:

Item {
width: 400
height: 400
Rectangle {
id: rect
anchors.fill: parent
color: "green"
}
Component.onCompleted: {
for (var i = 0; i < 1000; ++i) {
console.log("red", rect.color.r);
console.log("green", rect.color.g);
console.log("blue", rect.color.b);
console.log("alpha", rect.color.a);
}
}

Instead, we can use a variable to cache the data and avoid multiple look-ups on the same item over and over again:

Component.onCompleted: {
var rectColor = rect.color;
for (var i = 0; i < 1000; ++i) {
console.log("red", rectColor.r);
console.log("green", rectColor.g);
console.log("blue", rectColor.b);
console.log("alpha", rectColor.a);
}
}

Besides, if you change the property of a binding expression, especially in a loop, Qt will be forced to re-evaluate it repeatedly. This will cause some performances issue. Instead of doing this, the user should follow the next code snippet:

Item {
id: myItem
width: 400
height: 400
property int myValue: 0
Text {
anchors.fill: parent
text: myItem.myValue.toString()
}

Component.onCompleted: {
for (var i = 0; i < 1000; ++i) {
myValue += 1;
}
}
}

Instead, we can use a temporary variable for storing the data of myValue, then apply the final result back to myValue once the loop has been completed:

Component.onCompleted: {
var temp = myValue;
for (var i = 0; i < 1000; ++i) {
temp += 1;
}
myValue = temp;
}

Consider using an anchor to position your UI items instead of using bindings. Item positioning with bindings is really slow and inefficient, although it allows for maximum flexibility.