From d9e740d2ccf8c1d3caacfcd95537718048e3a7ba Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 11 Dec 2017 21:49:53 +0100 Subject: Migitate the performance regression caused by deferred execution 458eb65f7 introduced a performance regression. Before 458eb65f7, qmlbench delegates_button.qml results were around 40 frames on a TX1. After 458eb65f, it dropped to 32. This patch is unfortunately not able to bring it on the original level, but at least improves the results to 37. For QQuickText, it is extremely important that implicitWidth() gets called before the component is completed, to avoid doing implicit size calculation multiple times. Deferred execution caused a performance regression by creating contentItem in "one go". We need to split the deferred execution to two parts so that bindings get first setup, and later enabled upon completion. This way, we utilize QQuickText's performance optimization for implicit size calculation. Task-number: QTBUG-50992 Change-Id: I4bf00af71b6d7dbf1d4b58b00fe547c6c321f8ed Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickdeferredexecute.cpp | 29 +++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'src/quicktemplates2/qquickdeferredexecute.cpp') diff --git a/src/quicktemplates2/qquickdeferredexecute.cpp b/src/quicktemplates2/qquickdeferredexecute.cpp index 7ec4e8e8..802ed3d0 100644 --- a/src/quicktemplates2/qquickdeferredexecute.cpp +++ b/src/quicktemplates2/qquickdeferredexecute.cpp @@ -36,6 +36,7 @@ #include "qquickdeferredexecute_p_p.h" +#include #include #include #include @@ -45,6 +46,15 @@ QT_BEGIN_NAMESPACE namespace QtQuickPrivate { +typedef QHash DeferredStates; + +static inline uint qHash(QObject *object, const QString &propertyName) +{ + return ::qHash(object) + ::qHash(propertyName); +} + +Q_GLOBAL_STATIC(DeferredStates, deferredStates) + static void beginDeferred(QQmlEnginePrivate *enginePriv, const QQmlProperty &property, QQmlComponentPrivate::DeferredState *deferredState) { QObject *object = property.object(); @@ -89,20 +99,31 @@ static void beginDeferred(QQmlEnginePrivate *enginePriv, const QQmlProperty &pro } } -void executeDeferred(QObject *object, const QString &property) +void beginDeferred(QObject *object, const QString &property) { QQmlData *data = QQmlData::get(object); if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) { QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine); - QQmlComponentPrivate::DeferredState state; - beginDeferred(ep, QQmlProperty(object, property), &state); + QQmlComponentPrivate::DeferredState *state = new QQmlComponentPrivate::DeferredState; + beginDeferred(ep, QQmlProperty(object, property), state); // Release deferred data for those compilation units that no longer have deferred bindings data->releaseDeferredData(); - QQmlComponentPrivate::completeDeferred(ep, &state); + deferredStates()->insert(qHash(object, property), state); + } +} + +void completeDeferred(QObject *object, const QString &property) +{ + QQmlData *data = QQmlData::get(object); + QQmlComponentPrivate::DeferredState *state = deferredStates()->take(qHash(object, property)); + if (data && state && !data->wasDeleted(object)) { + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine); + QQmlComponentPrivate::completeDeferred(ep, state); } + delete state; } } // QtQuickPrivate -- cgit v1.2.3