// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
\page qtquick-performance.html
\meta {keywords} {qmltopic}
\title Performance considerations and suggestions
\keyword QML Performance Considerations And Suggestions
\brief Discussion of performance-related trade-offs and best-practices

\section1 Timing Considerations

As an application developer, you typically strive to allow the rendering
engine to achieve a consistent 60 frames-per-second refresh rate. Depending on
your hardware and requirements the number may be different, but 60 FPS is very
common. 60 FPS means that there is approximately 16 milliseconds between each
frame in which processing can be done, which includes the processing required
to upload the draw primitives to the graphics hardware.

In practice, this means that the application developer should:
\list
   \li use asynchronous, event-driven programming wherever possible
   \li use worker threads to do significant processing
   \li never manually spin the event loop
   \li never spend more than a couple of milliseconds per frame within blocking functions
\endlist

Failure to do so will result in skipped frames, which has a drastic effect on the
user experience.

\note A pattern which is tempting, but should \e never be used, is creating your
own QEventLoop or calling QCoreApplication::processEvents() in order to avoid
blocking within a C++ code block invoked from QML. This is dangerous, because
when an event loop is entered in a signal handler or binding, the QML engine
continues to run other bindings, animations, transitions, etc. Those bindings
can then cause side effects which, for example, destroy the hierarchy containing
your event loop.

\section1 Profiling

The most important tip is: use the \l{QML Profiler} included in \QC. Knowing
where time is spent in an application will allow you to focus on problem areas which
actually exist, rather than problem areas which potentially exist. See
\l{\QC: Profiling QML Applications} for more information.

Determining which bindings are being run the most often, or which functions your
application is spending the most time in, will allow you to decide whether you need
to optimize the problem areas, or redesign some implementation details of your
application so that the performance is improved. Attempting to optimize code without
profiling is likely to result in very minor rather than significant performance
improvements.

\section1 JavaScript Code

Most QML applications will have some JavaScript code in them, in the form of
property binding expressions, functions, and signal handlers. This is generally
not a problem. Thanks to advanced tooling such as the \l{Qt Quick Compiler},
simple functions and bindings can be very fast. However, care must be taken to
ensure that unnecessary processing isn't triggered accidentally. The
\l{QML Profiler} can show copious detail about JavaScript execution and what
triggered it.

\section2 Type-Conversion

One major cost of using JavaScript is that in some cases when a property from a QML
type is accessed, a JavaScript object with an external resource containing the
underlying C++ data (or a reference to it) is created. In most cases, this is fairly
inexpensive, but in others it can be quite expensive. Care is to be taken when
handling large and complicated \l{QML Value Types}{value types} or
\l{QML Sequence Types}{sequence types}. These have to be copied by the QML engine
whenever you change them in place or assign them to a different property. When this
becomes a bottleneck, consider using \l{QML Object Types}{object types} instead.
Lists of object types do not have the same problem as lists of value types because
lists of object types are implemented using \l{QQmlListProperty}.

Most conversions between simple value types are cheap. There are exceptions,
though. Creating a \e url from a \e string can involve constructing a \l{QUrl}
instance, which is costly.

\section2 Resolving Properties

Property resolution takes time. While lookups are typically optimized to run
much faster on subsequent executions, it is always best to avoid doing
unnecessary work altogether, if possible.

In the following example, we have a block of code which is run often (in this
case, it is the contents of an explicit loop; but it could be a
commonly-evaluated binding expression, for example) and in it, we resolve the
object with the "rect" id and its "color" property multiple times:

\qml
// bad.qml
import QtQuick

Item {
    width: 400
    height: 200
    Rectangle {
        id: rect
        anchors.fill: parent
        color: "blue"
    }

    function printValue(which: string, value: real) {
        console.log(which + " = " + value);
    }

    Component.onCompleted: {
        var t0 = new Date();
        for (var i = 0; i < 1000; ++i) {
            printValue("red", rect.color.r);
            printValue("green", rect.color.g);
            printValue("blue", rect.color.b);
            printValue("alpha", rect.color.a);
        }
        var t1 = new Date();
        console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations");
    }
}
\endqml

Every time \c{rect.color} is retrieved, the QML engine has to:
\list
\li Allocate a value type wrapper on the JavaScript heap.
\li Run the getter of \l{Rectangle}'s \c color property.
\li Copy the resulting \l{QColor} into the value type wrapper.
\endlist

We don't have to do this 4 times. We can instead resolve the common base
just once in the block:

\qml
// good.qml
import QtQuick

Item {
    width: 400
    height: 200
    Rectangle {
        id: rect
        anchors.fill: parent
        color: "blue"
    }

    function printValue(which: string, value: real) {
        console.log(which + " = " + value);
    }

    Component.onCompleted: {
        var t0 = new Date();
        for (var i = 0; i < 1000; ++i) {
            var rectColor = rect.color; // resolve the common base.
            printValue("red", rectColor.r);
            printValue("green", rectColor.g);
            printValue("blue", rectColor.b);
            printValue("alpha", rectColor.a);
        }
        var t1 = new Date();
        console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations");
    }
}
\endqml

Just this simple change results in a significant performance improvement.
Note that the code above can be improved even further (since the property
being looked up never changes during the loop processing), by hoisting the
property resolution out of the loop, as follows:

\qml
// better.qml
import QtQuick

Item {
    width: 400
    height: 200
    Rectangle {
        id: rect
        anchors.fill: parent
        color: "blue"
    }

    function printValue(which: string, value: real) {
        console.log(which + " = " + value);
    }

    Component.onCompleted: {
        var t0 = new Date();
        var rectColor = rect.color; // resolve the common base outside the tight loop.
        for (var i = 0; i < 1000; ++i) {
            printValue("red", rectColor.r);
            printValue("green", rectColor.g);
            printValue("blue", rectColor.b);
            printValue("alpha", rectColor.a);
        }
        var t1 = new Date();
        console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations");
    }
}
\endqml

\section2 Property Bindings

A property binding expression will be re-evaluated if any of the properties
it references are changed. As such, binding expressions should be kept as
simple as possible.

If you have a loop where you do some processing, but only the final result
of the processing is important, it is often better to update a temporary
accumulator which you afterwards assign to the property you need to update,
rather than incrementally updating the property itself, in order to avoid
triggering re-evaluation of binding expressions during the intermediate
stages of accumulation.

The following contrived example illustrates this point:

\qml
// bad.qml
import QtQuick

Item {
    id: root
    width: 200
    height: 200
    property int accumulatedValue: 0

    Text {
        anchors.fill: parent
        text: root.accumulatedValue.toString()
        onTextChanged: console.log("text binding re-evaluated")
    }

    Component.onCompleted: {
        var someData = [ 1, 2, 3, 4, 5, 20 ];
        for (var i = 0; i < someData.length; ++i) {
            accumulatedValue = accumulatedValue + someData[i];
        }
    }
}
\endqml

The loop in the onCompleted handler causes the "text" property binding to
be re-evaluated six times (which then results in any other property bindings
which rely on the text value, as well as the onTextChanged signal handler,
to be re-evaluated each time, and lays out the text for display each time).
This is clearly unnecessary in this case, since we really only care about
the final value of the accumulation.

It could be rewritten as follows:

\qml
// good.qml
import QtQuick

Item {
    id: root
    width: 200
    height: 200
    property int accumulatedValue: 0

    Text {
        anchors.fill: parent
        text: root.accumulatedValue.toString()
        onTextChanged: console.log("text binding re-evaluated")
    }

    Component.onCompleted: {
        var someData = [ 1, 2, 3, 4, 5, 20 ];
        var temp = accumulatedValue;
        for (var i = 0; i < someData.length; ++i) {
            temp = temp + someData[i];
        }
        accumulatedValue = temp;
    }
}
\endqml

\section2 Sequence tips

As mentioned earlier, \l{QML Sequence Types}{sequences of value types} have to
be handled with care.

Firstly, sequence types show different behavior in two distinct scenarios:
\list
\li if the sequence is a Q_PROPERTY of a QObject (we'll call this a reference
    sequence),
\li if the sequence is returned from a Q_INVOKABLE function of a QObject (we'll
    call this a copy sequence).
\endlist

A reference sequence is read and written via the \l{QMetaObject} whenever it
changes, either in your JavaScript code, or on the original object. As an
optimization, reference sequences (as well as reference
\l{QML Value Types}{value types}) may be loaded lazily. The actual content is
then only retrieved when they are first used. This means that changing the
value of any element in the sequence from JavaScript will result in:
\list
\li Possibly reading the content from the QObject (if lazy-loaded).
\li Changing the element at the specified index in that sequence.
\li Writing the whole sequence back to the QObject.
\endlist

A copy sequence is far simpler as the actual sequence is stored in the JavaScript
object's resource data, so no read/modify/write cycle occurs (instead, the resource
data is modified directly).

Therefore, writes to elements of a reference sequence will be much slower than writes
to elements of a copy sequence. In fact, writing to a single element of an N-element
reference sequence is equivalent in cost to assigning a N-element copy sequence to that
reference sequence, so you're usually better off modifying a temporary copy sequence
and then assigning the result to a reference sequence, during computation.

Assume the existence (and prior registration into the "Qt.example" namespace) of the
following C++ type:

\code
class SequenceTypeExample : public QQuickItem
{
    Q_OBJECT
    Q_PROPERTY (QList<qreal> qrealListProperty READ qrealListProperty WRITE setQrealListProperty NOTIFY qrealListPropertyChanged)

public:
    SequenceTypeExample() : QQuickItem() { m_list << 1.1 << 2.2 << 3.3; }
    ~SequenceTypeExample() {}

    QList<qreal> qrealListProperty() const { return m_list; }
    void setQrealListProperty(const QList<qreal> &list) { m_list = list; emit qrealListPropertyChanged(); }

signals:
    void qrealListPropertyChanged();

private:
    QList<qreal> m_list;
};
\endcode

The following example writes to elements of a reference sequence in a
tight loop, resulting in bad performance:

\qml
// bad.qml
import QtQuick
import Qt.example

SequenceTypeExample {
    id: root
    width: 200
    height: 200

    Component.onCompleted: {
        var t0 = new Date();
        qrealListProperty.length = 100;
        for (var i = 0; i < 500; ++i) {
            for (var j = 0; j < 100; ++j) {
                qrealListProperty[j] = j;
            }
        }
        var t1 = new Date();
        console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");
    }
}
\endqml

The QObject property read and write in the inner loop caused by the
\c{"qrealListProperty[j] = j"} expression makes this code very suboptimal. Instead,
something functionally equivalent but much faster would be:

\qml
// good.qml
import QtQuick
import Qt.example

SequenceTypeExample {
    id: root
    width: 200
    height: 200

    Component.onCompleted: {
        var t0 = new Date();
        var someData = [1.1, 2.2, 3.3]
        someData.length = 100;
        for (var i = 0; i < 500; ++i) {
            for (var j = 0; j < 100; ++j) {
                someData[j] = j;
            }
            qrealListProperty = someData;
        }
        var t1 = new Date();
        console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");
    }
}
\endqml

Another common pattern that should be avoided is read-modify-write loops where each
element is read, modified, and written back to the sequence property. Similar to the
previous example, this causes QObject property reads and writes in every iteration:

\qml
// bad.qml
import QtQuick
import Qt.example

SequenceTypeExample {
    id: root
    width: 200
    height: 200

    Component.onCompleted: {
        var t0 = new Date();
        qrealListProperty.length = 100;
        for (var i = 0; i < 500; ++i) {
            for (var j = 0; j < 100; ++j) {
                qrealListProperty[j] = qrealListProperty[j] * 2;
            }
        }
        var t1 = new Date();
        console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");
    }
}
\endqml

Instead, create a manual copy of the sequence, modify the copy, and then assign
the result back to the property:

\qml
// good.qml
import QtQuick
import Qt.example

SequenceTypeExample {
    id: root
    width: 200
    height: 200

    Component.onCompleted: {
        var t0 = new Date();
        for (var i = 0; i < 500; ++i) {
            let data = [...qrealListProperty];
            for (var j = 0; j < 100; ++j) {
                data[j] = data[j] * 2;
            }
            qrealListProperty = data;
        }
        var t1 = new Date();
        console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");
    }
}
\endqml

Secondly, a change signal for the property is emitted if any element in it changes.
If you have many bindings to a particular element in a sequence property, it is better
to create a dynamic property which is bound to that element, and use that dynamic
property as the symbol in the binding expressions instead of the sequence element,
as it will only cause re-evaluation of bindings if its value changes.

This is an unusual use-case which most clients should never hit, but is worth being
aware of, in case you find yourself doing something like this:

\qml
// bad.qml
import QtQuick
import Qt.example

SequenceTypeExample {
    id: root

    property int firstBinding: qrealListProperty[1] + 10;
    property int secondBinding: qrealListProperty[1] + 20;
    property int thirdBinding: qrealListProperty[1] + 30;

    Component.onCompleted: {
        var t0 = new Date();
        for (var i = 0; i < 1000; ++i) {
            qrealListProperty[2] = i;
        }
        var t1 = new Date();
        console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");
    }
}
\endqml

Note that even though only the element at index 2 is modified in the loop, the three
bindings will all be re-evaluated since the granularity of the change signal is that
the entire property has changed. As such, adding an intermediate binding can
sometimes be beneficial:

\qml
// good.qml
import QtQuick
import Qt.example

SequenceTypeExample {
    id: root

    property int intermediateBinding: qrealListProperty[1]
    property int firstBinding: intermediateBinding + 10;
    property int secondBinding: intermediateBinding + 20;
    property int thirdBinding: intermediateBinding + 30;

    Component.onCompleted: {
        var t0 = new Date();
        for (var i = 0; i < 1000; ++i) {
            qrealListProperty[2] = i;
        }
        var t1 = new Date();
        console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");
    }
}
\endqml

In the above example, only the intermediate binding will be re-evaluated each time,
resulting in a significant performance increase.

\section2 Value-Type tips

\l{QML Value Types}{Value type} properties (font, color, vector3d, etc) have
similar QObject property and change notification semantics to sequence type
properties. As such, the tips given above for sequences are also applicable for
value type properties. While they are usually less of a problem with value
types (since the number of sub-properties of a value type is usually far less
than the number of elements in a sequence), any increase in the number of
bindings being re-evaluated needlessly will have a negative impact on
performance.

\section2 General Performance Tips

General JavaScript performance considerations resulting from the language
design are applicable also to QML. Most prominently:

\list
\li Avoid using eval() if at all possible
\li Do not delete properties of objects
\endlist

\section1 Common Interface Elements

\section2 Text Elements

Calculating text layouts can be a slow operation. Consider using the \c PlainText
format instead of \c StyledText wherever possible, as this reduces the amount of work
required of the layout engine. If you cannot use \c PlainText (as you need to embed
images, or use tags to specify ranges of characters to have certain formatting (bold,
italic, etc) as opposed to the entire text) then you should use \c StyledText.

You should only use \c AutoText if the text might be (but probably isn't)
\c StyledText as this mode will incur a parsing cost. The \c RichText mode should
not be used, as \c StyledText provides almost all of its features at a fraction of
its cost.

\section2 Images

Images are a vital part of any user interface. Unfortunately, they are also a big
source of problems due to the time it takes to load them, the amount of memory they
consume, and the way in which they are used.

\section3 Asynchronous Loading

Images are often quite large, and so it is wise to ensure that loading an image doesn't
block the UI thread. Set the "asynchronous" property of the QML Image element to
\c true to enable asynchronous loading of images from the local file system (remote
images are always loaded asynchronously) where this would not result in a negative impact
upon the aesthetics of the user interface.

Image elements with the "asynchronous" property set to \c true will load images in
a low-priority worker thread.

\section3 Explicit Source Size

If your application loads a large image but displays it in a small-sized element, set
the "sourceSize" property to the size of the element being rendered to ensure that the
smaller-scaled version of the image is kept in memory, rather than the large one.

Beware that changing the sourceSize will cause the image to be reloaded.

\section3 Avoid Run-time Composition

Also remember that you can avoid doing composition work at run-time by providing the
pre-composed image resource with your application (for example, providing elements with shadow
effects).

\section3 Avoid Smoothing Images

Enable \c{image.smooth} only if required. It is slower on some hardware, and it has no visual
effect if the image is displayed in its natural size.

\section3 Painting

Avoid painting the same area several times. Use Item as root element rather than Rectangle
to avoid painting the background several times.

\section2 Position Elements With Anchors

It is more efficient to use anchors rather than bindings to position items
relative to each other. Consider this use of bindings to position rect2
relative to rect1:

\code
Rectangle {
    id: rect1
    x: 20
    width: 200; height: 200
}
Rectangle {
    id: rect2
    x: rect1.x
    y: rect1.y + rect1.height
    width: rect1.width - 20
    height: 200
}
\endcode

This is achieved more efficiently using anchors:

\code
Rectangle {
    id: rect1
    x: 20
    width: 200; height: 200
}
Rectangle {
    id: rect2
    height: 200
    anchors.left: rect1.left
    anchors.top: rect1.bottom
    anchors.right: rect1.right
    anchors.rightMargin: 20
}
\endcode

Positioning with bindings (by assigning binding expressions to the x, y, width
and height properties of visual objects, rather than using anchors) is
relatively slow, although it allows maximum flexibility.

If the layout is not dynamic, the most performant way to specify the layout is
via static initialization of the x, y, width and height properties. Item
coordinates are always relative to their parent, so if you wanted to be a fixed
offset from your parent's 0,0 coordinate you should not use anchors. In the
following example the child Rectangle objects are in the same place, but the
anchors code shown is not as resource efficient as the code which
uses fixed positioning via static initialization:

\code
Rectangle {
    width: 60
    height: 60
    Rectangle {
        id: fixedPositioning
        x: 20
        y: 20
        width: 20
        height: 20
    }
    Rectangle {
        id: anchorPositioning
        anchors.fill: parent
        anchors.margins: 20
    }
}
\endcode

\section1 Models and Views

Most applications will have at least one model feeding data to a view. There are
some semantics which application developers need to be aware of, in order to achieve
maximal performance.

\section2 Custom C++ Models

It is often desirable to write your own custom model in C++ for use with a view in
QML. While the optimal implementation of any such model will depend heavily on the
use-case it must fulfil, some general guidelines are as follows:

\list
\li Be as asynchronous as possible
\li Do all processing in a (low priority) worker thread
\li Batch up backend operations so that (potentially slow) I/O and IPC is minimized
\endlist

It is important to note that using a low-priority worker thread is recommended to
minimize the risk of starving the GUI thread (which could result in worse perceived
performance). Also, remember that synchronization and locking mechanisms can be a
significant cause of slow performance, and so care should be taken to avoid
unnecessary locking.

\section2 ListModel QML Type

\l{Qt Qml Models} provides a \l{ListModel} type which can be used to feed data
to a \l{ListView}. It is useful for quick prototyping, but not suitable for
larger amounts of data. Use a proper \l{QAbstractItemModel} where necessary.

\section3 Populate Within A Worker Thread

\l{ListModel} elements can be populated in a (low priority) worker thread in
JavaScript. The developer must explicitly call \c{sync()} on the \l{ListModel}
from within the \l{WorkerScript} to have the changes synchronized to the main
thread. See the \l{WorkerScript} documentation for more information.

Please note that using a \l{WorkerScript} element will result in a separate
JavaScript engine being created (as the JavaScript engine is per-thread). This
will result in increased memory usage. Multiple \l{WorkerScript} elements will
all use the same worker thread, however, so the memory impact of using a second
or third \l{WorkerScript} element is negligible once an application already
uses one. On the flip side, however, the additional worker scripts do not run
in parallel.

\section3 Don't Use Dynamic Roles

The \l{ListModel} element assumes the types of roles within each element in a
given model are stable for optimization purposes. If the type can change
dynamically from element to element, the performance of the model will be much
worse.

Therefore, dynamic typing is disabled by default; the developer must
specifically set the boolean \c{dynamicRoles} property of the model to enable
dynamic typing (and suffer the attendant performance degradation). We recommend
that you do not use dynamic typing unless absolutely necessary.

\section2 Views

View delegates should be kept as simple as possible. Have just enough QML in
the delegate to display the necessary information. Any additional functionality
which is not immediately required (for example, if it displays more information
when clicked) should not be created until needed (see the upcoming section on
lazy initialization).

The following list is a good summary of things to keep in mind when designing a
delegate:
\list
\li The fewer elements that are in a delegate, the faster they can be created,
    and thus the faster the view can be scrolled.
\li Keep the number of bindings in a delegate to a minimum; in particular, use
    anchors rather than bindings for relative positioning within a delegate.
\li Avoid using \l{ShaderEffect} elements within delegates.
\li Never enable clipping on a delegate.
\endlist

You may set the \c cacheBuffer property of a view to allow asynchronous
creation and buffering of delegates outside of the visible area. Utilizing a
\c cacheBuffer is recommended for view delegates that are non-trivial and
unlikely to be created within a single frame.

Bear in mind that a \c cacheBuffer keeps additional delegates in-memory.
Therefore, the value derived from utilizing the \c cacheBuffer must be balanced
against additional memory usage. Developers should use benchmarking to find the
best value for their use-case, since the increased memory pressure caused by
utilizing a \c cacheBuffer can, in some rare cases, cause reduced frame rate
when scrolling.

For additional performance improvements, consider enabling item reuse in views.
See \l{qml-qtquick-listview.html#reusing-items}{Reusing Items for ListView} and
\l{qml-qtquick-tableview.html#reusing-items}{Reusing Items for TableView and
TreeView} for more information.

\section1 Visual Effects

\l{Qt Quick} includes several features which allow developers and designers to
create exceptionally appealing user interfaces. Fluidity and dynamic transitions
as well as visual effects can be used to great effect in an application, but
some care must be taken when using some of the features in QML as they can have
performance implications.

\section2 Animations

In general, animating a property will cause any bindings which reference that property
to be re-evaluated. Usually, this is what is desired but in other cases it may be better
to disable the binding prior to performing the animation, and then reassign the binding
once the animation has completed.

Avoid running JavaScript during animation. For example, running a complex JavaScript
expression for each frame of an x property animation should be avoided.

Developers should be especially careful using script animations, as these are run in the main
thread (and therefore can cause frames to be skipped if they take too long to complete).

\section2 Particles

The \l{QtQuick.Particles}{Qt Quick Particles} module allows beautiful particle effects to be integrated
seamlessly into user interfaces. However, every platform has different graphics hardware
capabilities, and the Particles module is unable to limit parameters to what your hardware
can gracefully support. The more particles you attempt to render (and the larger they are),
the faster your graphics hardware will need to be in order to render at 60 FPS. Affecting
more particles requires a faster CPU. It is therefore important to test all
particle effects on your target platform carefully, to calibrate the number and size of
particles you can render at 60 FPS.

It should be noted that a particle system can be disabled when not in use
(for example, on a non-visible element) to avoid doing unnecessary simulation.

See the \l{Particle System Performance Guide} for more in-depth information.

\section1 Controlling Element Lifetime

By partitioning an application into simple, modular components, each contained in a single
QML file, you can achieve faster application startup time and better control over memory
usage, and reduce the number of active-but-invisible elements in your application.

\section2 Lazy Initialization

The QML engine does some tricky things to try to ensure that loading and initialization of
components doesn't cause frames to be skipped. However, there is no better way to reduce
startup time than to avoid doing work you don't need to do, and delaying the work until
it is necessary. This may be achieved by using either \l{Loader}.

\section3 Using Loader

The Loader is an element which allows dynamic loading and unloading of components.

\list
\li Using the "active" property of a Loader, initialization can be delayed until required.
\li Using the overloaded version of the "setSource()" function, initial property values can
   be supplied.
\li Setting the Loader \l {Loader::asynchronous}{asynchronous} property to true may also
   improve fluidity while a component is instantiated.
\endlist

\section2 Destroy Unused Elements

Elements which are invisible because they are a child of a non-visible element (for example, the
second tab in a tab-widget, while the first tab is shown) should be initialized lazily in
most cases, and deleted when no longer in use, to avoid the ongoing cost of leaving them
active (for example, rendering, animations, property binding evaluation, etc).

An item loaded with a Loader element may be released by resetting the "source" or
"sourceComponent" property of the Loader, while other items may be explicitly
released by calling destroy() on them. In some cases, it may be necessary to
leave the item active, in which case it should be made invisible at the very least.

See the upcoming section on Rendering for more information on active but invisible elements.

\section1 Rendering

The scene graph used for rendering in \l{Qt Quick} allows highly dynamic, animated user
interfaces to be rendered fluidly at 60 FPS. There are some things which can
dramatically decrease rendering performance, however, and developers should be careful
to avoid these pitfalls wherever possible.

\target clipping-performance
\section2 Clipping

Clipping is disabled by default, and should only be enabled when required.

Clipping is a visual effect, NOT an optimization. It increases (rather than reduces)
complexity for the renderer. If clipping is enabled, an item will clip its own painting,
as well as the painting of its children, to its bounding rectangle. This stops the renderer
from being able to reorder the drawing order of elements freely, resulting in a sub-optimal
best-case scene graph traversal.

Clipping inside a delegate is especially bad and should be avoided at all costs.

\section2 Over-drawing and Invisible Elements

If you have elements which are totally covered by other (opaque) elements, it is best to
set their "visible" property to \c false or they will be drawn needlessly.

Similarly, elements which are invisible (for example, the second tab in a tab widget, while the
first tab is shown) but need to be initialized at startup time (for example, if the cost of
instantiating the second tab takes too long to be able to do it only when the tab is
activated), should have their "visible" property set to \c false, in order to avoid the
cost of drawing them (although as previously explained, they will still incur the cost of
any animations or bindings evaluation since they are still active).

\section2 Translucent vs Opaque

Opaque content is generally a lot faster to draw than translucent. The reason being
that translucent content needs blending and that the renderer can potentially optimize
opaque content better.

An image with one translucent pixel is treated as fully translucent, even though it
is mostly opaque. The same is true for an \l BorderImage with transparent edges.

\section2 Shaders

The \l ShaderEffect type makes it possible to place GLSL code inline in a Qt Quick application with
very little overhead. However, it is important to realize that the fragment program needs to run
for every pixel in the rendered shape. When deploying to low-end hardware and the shader
is covering a large amount of pixels, one should keep the fragment shader to a few instructions
to avoid poor performance.

Shaders written in GLSL allow for complex transformations and visual effects to be written,
however they should be used with care. Using a \l ShaderEffectSource causes a scene to be
prerendered into an FBO before it can be drawn. This extra overhead can be quite expensive.

\section1 Memory Allocation And Collection

The amount of memory which will be allocated by an application and the way in which that
memory will be allocated are very important considerations. Aside from the obvious
concerns about out-of-memory conditions on memory-constrained devices, allocating memory
on the heap is a fairly computationally expensive operation, and certain allocation
strategies can result in increased fragmentation of data across pages. JavaScript uses
a managed memory heap which is automatically garbage collected, and this has some
advantages, but also some important implications.

An application written in QML uses memory from both the C++ heap and an automatically
managed JavaScript heap. The application developer needs to be aware of the subtleties
of each in order to maximise performance.

\section2 Tips For QML Application Developers

The tips and suggestions contained in this section are guidelines only, and may not be
applicable in all circumstances. Be sure to benchmark and analyze your application
carefully using empirical metrics, in order to make the best decisions possible.

\section3 Instantiate and initialize components lazily

If your application consists of multiple views (for example, multiple tabs) but only
one is required at any one time, you can use lazy instantiation to minimize the
amount of memory you need to have allocated at any given time. See the prior section
on \l{Lazy Initialization} for more information.

\section3 Destroy unused objects

If you lazy load components, or create objects dynamically during a JavaScript
expression, it is often better to \c{destroy()} them manually rather than wait for
automatic garbage collection to do so. See the prior section on
\l{Controlling Element Lifetime} for more information.

\section3 Don't manually invoke the garbage collector

In most cases, it is not wise to manually invoke the garbage collector, as it will block
the GUI thread for a substantial period of time. This can result in skipped frames and
jerky animations, which should be avoided at all costs.

There are some cases where manually invoking the garbage collector is acceptable (and
this is explained in greater detail in an upcoming section), but in most cases, invoking
the garbage collector is unnecessary and counter-productive.

\section3 Avoid defining multiple identical implicit types

If a QML element has a custom property defined in QML, it becomes its own implicit type.
This is explained in greater detail in an upcoming section. If multiple identical
implicit types are defined in a \l{Component}, some memory will be wasted. In that
situation it is usually better to explicitly define a new component which can then be
reused. Consider defining an inline component using the \c{component} keyword in such
a case.

Defining a custom property can often be a beneficial performance optimization (for
example, to reduce the number of bindings which are required or re-evaluated), or it
can improve the modularity and maintainability of a component. In those cases, using
custom properties is encouraged. However, the new type should, if it is used more than
once, be split into its own component (inline or .qml file) in order to conserve memory.

\section3 Reuse existing components

If you are considering defining a new component, it's worth double checking that such a
component doesn't already exist in the component set for your platform. Otherwise, you
will be forcing the QML engine to generate and store type-data for a type which is
essentially a duplicate of another pre-existing and potentially already loaded component.

\section3 Use singleton types instead of pragma library scripts

If you are using a pragma library script to store application-wide instance data,
consider using a QObject singleton type instead. This should result in better performance,
and will result in less JavaScript heap memory being used.

\section2 Memory Allocation in a QML Application

The memory usage of a QML application may be split into two parts: its C++ heap usage
and its JavaScript heap usage. Some of the memory allocated in each will be unavoidable,
as it is allocated by the QML engine or the JavaScript engine, while the rest is
dependent upon decisions made by the application developer.

The C++ heap will contain:
\list
  \li the fixed and unavoidable overhead of the QML engine (implementation data
  structures, context information, and so on);
  \li per-component compiled data and type information, including per-type property
  metadata, which is generated or loaded from the \l{The QML Disk Cache}{disk cache}
  by the QML engine depending on which modules and which components are loaded by the
  application;
  \li per-object C++ data (including property values) plus a per-element metaobject
  hierarchy, depending on which components the application instantiates;
  \li any data which is allocated specifically by QML imports (libraries).
\endlist

The JavaScript heap will contain:
\list
  \li the fixed and unavoidable overhead of the JavaScript engine itself (including
  built-in JavaScript types);
  \li the fixed and unavoidable overhead of our JavaScript integration (constructor
  functions for loaded types, function templates, and so on);
  \li per-type layout information and other internal type-data generated by the JavaScript
  engine at runtime, for each type (see note below, regarding types);
  \li per-object JavaScript data ("var" properties, JavaScript functions and signal
  handlers, and non-optimized binding expressions);
  \li variables allocated during expression evaluation.
\endlist

Furthermore, there will be one JavaScript heap allocated for use in the main thread, and
optionally one other JavaScript heap allocated for use in the WorkerScript thread. If an
application does not use a WorkerScript element, that overhead will not be incurred. The
JavaScript heap can be several megabytes in size, and so applications written for
memory-constrained devices may be best served by avoiding the WorkerScript element.

Note that both the QML engine and the JavaScript engine will automatically generate their
own caches of type-data about observed types. Every component loaded by an application
is a distinct (explicit) type, and every element (component instance) that defines its
own custom properties in QML is an implicit type. Any element (instance of a component)
that does not define any custom property is considered by the JavaScript and QML engines
to be of the type explicitly defined by the component, rather than its own implicit type.

Consider the following example:
\qml
import QtQuick

Item {
    id: root

    Rectangle {
        id: r0
        color: "red"
    }

    Rectangle {
        id: r1
        color: "blue"
        width: 50
    }

    Rectangle {
        id: r2
        property int customProperty: 5
    }

    Rectangle {
        id: r3
        property string customProperty: "hello"
    }

    Rectangle {
        id: r4
        property string customProperty: "hello"
    }
}
\endqml

In the previous example, the rectangles \c r0 and \c r1 do not have any custom properties,
and thus the JavaScript and QML engines consider them both to be of the same type. That
is, \c r0 and \c r1 are both considered to be of the explicitly defined \c Rectangle type.
The rectangles \c r2, \c r3 and \c r4 each have custom properties and are each considered
to be of different (implicit) types. Note that \c r3 and \c r4 are each considered to be of
different types, even though they have identical property information, simply because the
custom property was not declared in the component which they are instances of.

If \c r3 and \c r4 were both instances of a \c RectangleWithString component, and that
component definition included the declaration of a string property named \c customProperty,
then \c r3 and \c r4 would be considered to be of the same type (that is, they would be
instances of the \c RectangleWithString type, rather than defining their own implicit type).

\section2 In-Depth Memory Allocation Considerations

Whenever making decisions regarding memory allocation or performance trade-offs, it is
important to keep in mind the impact of CPU-cache performance, operating system paging,
and JavaScript engine garbage collection. Potential solutions should be benchmarked
carefully in order to ensure that the best one is selected.

No set of general guidelines can replace a solid understanding of the underlying
principles of computer science combined with a practical knowledge of the implementation
details of the platform for which the application developer is developing. Furthermore,
no amount of theoretical calculation can replace a good set of benchmarks and analysis
tools when making trade-off decisions.

\section3 Fragmentation

Fragmentation is a C++ development issue. If the application developer is not defining
any C++ types or plugins, they may safely ignore this section.

Over time, an application will allocate large portions of memory, write data to that
memory, and subsequently free some portions of it once it has finished using
some of the data. This can result in "free" memory being located in non-contiguous
chunks, which cannot be returned to the operating system for other applications to use.
It also has an impact on the caching and access characteristics of the application, as
the "living" data may be spread across many different pages of physical memory. This
in turn could force the operating system to swap, which can cause filesystem I/O - which
is, comparatively speaking, an extremely slow operation.

Fragmentation can be avoided by utilizing pool allocators (and other contiguous memory
allocators), by reducing the amount of memory which is allocated at any one time by
carefully managing object lifetimes, by periodically cleansing and rebuilding caches,
or by utilizing a memory-managed runtime with garbage collection (such as JavaScript).

\section3 Garbage Collection

JavaScript provides garbage collection. Memory which is allocated on the JavaScript
heap (as opposed to the C++ heap) is owned by the JavaScript engine. The engine will
periodically collect all unreferenced data on the JavaScript heap.

\section4 Implications of Garbage Collection

Garbage collection has advantages and disadvantages. It means that manually managing
object lifetime is less important.
However, it also means that a potentially long-lasting operation may be initiated by the
JavaScript engine at a time which is out of the application developer's control. Unless
JavaScript heap usage is considered carefully by the application developer, the frequency
and duration of garbage collection may have a negative impact upon the application
experience. Since Qt 6.8, the garbage collector is incremental, which means it will
incur shorter, but potentially more interruptions.

\section4 Manually Invoking the Garbage Collector

An application written in QML will (most likely) require garbage collection to be
performed at some stage. While garbage collection will be automatically triggered by
the JavaScript engine on its own schedule, it is occasionally better if the
application developer makes decisions about when to invoke the garbage
collector manually (although usually this is not the case).

The application developer is likely to have the best understanding of when an application
is going to be idle for substantial periods of time. If a QML application uses a lot
of JavaScript heap memory, causing regular and disruptive garbage collection cycles
during particularly performance-sensitive tasks (for example, list scrolling, animations,
and so forth), the application developer may be well served to manually invoke the
garbage collector during periods of zero activity. Idle periods are ideal for performing
garbage collection since the user will not notice any degradation of user experience
(skipped frames, jerky animations, and so on) which would result from invoking the garbage
collector while activity is occurring.

The garbage collector may be invoked manually by calling \c{gc()} within JavaScript.
This will cause a full, non-incremental collection cycle to be performed, which
may take from between a few hundred to more than a thousand milliseconds to complete, and
so should be avoided if at all possible.

\section3 Memory vs Performance Trade-offs

In some situations, it is possible to trade-off increased memory usage for decreased
processing time. For example, caching the result of a symbol lookup used in a tight loop
to a temporary variable in a JavaScript expression will result in a significant performance
improvement when evaluating that expression, but it involves allocating a temporary variable.
In some cases, these trade-offs are sensible (such as the case above, which is almost always
sensible), but in other cases it may be better to allow processing to take slightly longer
in order to avoid increasing the memory pressure on the system.

In some cases, the impact of increased memory pressure can be extreme. In some situations,
trading off memory usage for an assumed performance gain can result in increased page-thrash
or cache-thrash, causing a huge reduction in performance. It is always necessary to benchmark
the impact of trade-offs carefully in order to determine which solution is best in a given
situation.

For in-depth information on cache performance and memory-time trade-offs, refer to the following
articles:
\list
    \li Ulrich Drepper's excellent article: "What Every Programmer Should Know About Memory",
        at: \l{https://people.freebsd.org/~lstewart/articles/cpumemory.pdf}.
    \li Agner Fog's excellent manuals on optimizing C++ applications at:
        \l{http://www.agner.org/optimize/}.
\endlist

\section1 Fast Boot and Startup Optimization

Based on real-world experience optimizing Qt Quick applications for fast boot,
consider the following best practices:

\list
\li Design your application to start fast from the beginning. Think what you
    want the user to see first.
\li Use the \l{QML Profiler} to identify bottlenecks in startup.
\li Use chain loading. Run only as many \l{Loader}{loaders} as you have cores
    in your CPU (e.g two cores: two loaders running at the same time).
\li The first \l{Loader}{loader} should not be asynchronous, so that some
    content is shown immediately. Trigger the asynchronous loaders after.
\li Connect to back-end services only when required.
\li Create \l{QML Modules} that are imported when required. Using lazily-loaded
    modules and types you can can make non-critical services available to your
    application as needed.
\li Optimize your PNG/JPG images using tools such as optipng.
\li Optimize your 3D models by reducing the amount of vertices and removing
    parts that are not visible.
\li Optimise the 3D model loading by using glTF.
\li Limit use of clip and opacity, as these can impact performance.
\li Measure GPU limitations and take those into account when designing the UI.
    See \l{qrhi.html#frame-captures-and-performance-profiling}{Frame Captures
    and Performance Profiling} for more information.
\li Use \l{Qt Quick Compiler} to pre-compile the QML files.
\li Investigate if static linking is possible for your architecture.
\li Strive for declarative bindings instead of imperative signal handlers.
\li Keep property bindings simple. In general, keep QML code simple, fun and
    readable. Good performance follows.
\li Replace complex controls with images or shaders if creation time is an
    issue.
\endlist

Do not:
\list
\li Go overboard with QML. Even if you use QML, you don’t need to do absolutely
    everything in QML.
\li Initialize everything in your main.cpp.
\li Create big singletons that contain all the required interfaces.
\li Create complex delegates for \l{ListView} or other views.
\li Use clip unless absolutely necessary.
\li Fall into the common trap of overusing Loaders. \l{Loader} is great for
    lazy-loading larger things like application pages, but introduces too much
    overhead for loading simple things. It’s not black magic that speeds up
    anything and everything. It’s an extra item with an extra QML context.
\endlist

These practices help achieve sub-second startup times and smooth user
experiences, especially on embedded devices.

*/
