[Development] Item creation time in QML

Andrew den Exter andrew.den.exter at qinetic.com.au
Fri Feb 13 00:41:19 CET 2015


>
> Is creation expensive because of constructor code, making too many
> signal/slot connections, or something else?
>

First of all it's accumulative, any QML application is going to end up
constructing many items, hundreds, thousands even and costs, even small
ones add up.  Secondly yes constructing and interacting with QObjects can
be expensive and there are ways to mitigate some of those costs.   Thirdly
parsing, compiling, instantiating, and executing bindings is all extra work
that comes at a cost.

Robin's singled out the Text items so lets have a look at those.  A good
amount of work has already been put into these items though so TextEdit
aside there's not a lot of low hanging fruit.

I'll list some slightly more detailed benchmarks below, but my imperfect
measure on the same device a raw Item takes around 30us to construct and
Text about 50us.  That extra time is spent initializing many primitives,
setting a couple of QQuickItem flags, executing the default constructors
for a couple of QLists, a QUrl, a QString, two QFonts, and a QLayout, and
attempting to determine the default layout direction.  From memory if you
profiled you'd find most of that time was in the QFont constructors,
including those in QLayout.

TextInput is the next slowest at about 80us.  It mostly has the same
initialization as a Text except it calls QClipboard::supportsSelection(),
and connects to QClipboard's dataChanged() signal.  That surprisingly uses
the traditional connect method which is almost universally shunned in
QtDeclarative code.  If I change that to a qmlobject_connect that time goes
down to 65ms, 20% right there.

TextEdit is a behemoth at about 420us.  A lot of that is QTextDocument
which is also why Text is so much slower with RichText.  The rest is mostly
because a lot of the implementation is in QQuickTextControl (extra QObject
allocation) and there are many signal/slot connections between
QTextDocument, QQuickTextControl, and QQuickTextEdit.  If anyone's looking
for a project, folding QQuickTextControl into QQuickText would yield a
decent improvement in absolute construction time.

Note these are pure instantiation times, when the items have to do actual
work the numbers climb again. Just setting a property such as Text {
horizontalAlignment: Text.AlignLeft } gives a time closer to 65us, and a
setting some text so a layout is actually performed like Text { text:
"hello world" } brings it up to the 120us mark for example.  An then
slightly decoupled from that in the real world that item is a member of a
scene graph and constructing the scene graph node add costs on top of that.


As for what you can do, first and foremost measure and compare.  Item
(~30us) to ListView (~80us) represent what I think are the boundaries of
reasonable expectation for performance, if you're exceeding ListView
something's probably wrong, try and aim for Item though.  Otherwise there
are a few common traps to avoid:

Create fewer QObjects, if you don't absolutely need it you don't want it.
Minimise signal/slot connections, use a connect mechanism that caches the
signal index if you do
Another unexpected one I don't have demonstrative times for right now is
QObject::setParent() or even just passing the parent to the QObject
constructor I think.  That will send a ParentChange event which eats up a
noticeable amount of time usually to no effect, internally QtDeclarative
avoids this by calling QQml_setParent_noEvent instead.
Defer work caused by property writes until componentComplete() or a polish
event if possible, there's no point re-evaluating something if it's
immediately invalided by a subsequent property change.  Text doesn't do the
latter right now which means it can be more expensive to make multiple
changes to an already constructed Text item than create a new one.


Andrew


The times below were measured using
https://github.com/adenexter/qml-benchmarks on a 1.4GHz dual core arm
device, your results will vary.

Measuring construction time of Item over 100 iterations

 import QtQuick 2.0


Item {

}

 One time parse time (ns)         1,037,692

One time construction time (ns): 91,561

Average construction time (ns):  29,909

Average destruction time (ns):   10,682

 Measuring construction time of Text over 100 iterations

 import QtQuick 2.0


Text {

}

 One time parse time (ns)         1,800,702

One time construction time (ns): 15,016,023

Average construction time (ns):  47,306

Average destruction time (ns):   21,059

 Measuring construction time of TextInput over 100 iterations

 import QtQuick 2.0


TextInput {

}

 One time parse time (ns)         1,892,263

One time construction time (ns): 396,765

Average construction time (ns):  80,573

Average destruction time (ns):   15,565

 Measuring construction time of TextEdit over 100 iterations

 import QtQuick 2.0


TextEdit {

}

 One time parse time (ns)         1,739,662

One time construction time (ns): 1,495,498

Average construction time (ns):  449,870

Average destruction time (ns):   73,859



qmlobject_connect(QGuiApplication::clipboard(), QClipboard,
SIGNAL(dataChanged()),

        q, QQuickTextInput, SLOT(q_canPasteChanged()));


Measuring construction time of TextInput over 100 iterations


import QtQuick 2.0


TextInput {

}

 One time parse time (ns)         1,800,702

One time construction time (ns): 427,286

Average construction time (ns):  65,924

Average destruction time (ns):   16,175


QObject::connect(QGuiApplication::clipboard(), &QClipboard::dataChanged,

        q, &QQuickTextInput::q_canPasteChanged);


Measuring construction time of TextInput over 100 iterations


import QtQuick 2.0


TextInput {

 One time parse time (ns)         1,800,702

One time construction time (ns): 396,765

Average construction time (ns):  69,586

Average destruction time (ns):   14,954


Measuring construction time of TextEdit over 100 iterations


import QtQuick 2.0


No connection



Measuring construction time of TextInput over 100 iterations


import QtQuick 2.0


TextInput {

}

 One time parse time (ns)         1,831,222

One time construction time (ns): 366,245

Average construction time (ns):  62,261

Average destruction time (ns):   14,649
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20150213/4f895fb5/attachment.html>


More information about the Development mailing list