Discussion:
QTBUG-43096 - QML instantiation performance decadence
(too old to reply)
Uwe Rathmann
2018-05-25 11:12:27 UTC
Permalink
Hi all,

this morning I got a notification about
https://bugreports.qt.io/browse/QTBUG-43096
being closed. I guess many applications had been hit by this issue, but
as I was related to the project that created this bug I would like to
give my summary of what has happened since then:

a)

On the Qt development side a lot of efforts have been made to improve
the QML problem. I don't want to be disrespectful, but the fact, that
Controls 1 has finally become deprecated, because of ( IIRC )
"insolvable performance problems", it is fair say, that those were no
game changers.

So to me the only step that really matters was introducing Qt/Quick
Controls 2.

But what makes Controls 2 being superior compared to its predecessor ?
AFAIK the answer is mostly about doing less QML, achieved by:

- dropping features ( usually desktop related )
- internally done in C++

Of course this raises the question, why there is no offer for doing more
in C++ on the application side, when it has been identified as the
solution for implementing the controls ?

And this is why I'm disappointed about Controls 2. Application code still
has to be done in QML and when the majority of the GUI code is
application code the benefits of Controls 2 are limited.

b)

On our side the the decision was made to go back to Qt 5.1, where the
project is stuck until today.

Almost all developers of the original team are gone - none
of them recommending QML as technology for further projects. Even worse
- some of them explicitly mentioned QML being a reason for leaving.

So for the next generation of our product we started to implement our
own framework on top of the C++ part of Qt/Quick (
https://github.com/uwerat/qskinny ). Our user interface today consists
about ~200K lines of code ( pure C++ ) and so far I can say that the
typical problems of having a bad startup performance or the heavy memory
footprint simple don't exist.

Unfortunately we still have to maintain our previous product written in
QML for many years. Maybe we can migrate it step by step to our new
framework.

With all respect,
Uwe
Robin Burchell
2018-05-25 12:30:05 UTC
Permalink
Hi Uwe,

I had predicted a response, so this mail comes as no surprise to me :)

Personal opinions on various things ahead, the reader may disagree with me, that's perfectly normal and OK.

From my own perspective, I think Controls 1 was a well-intentioned mistake. It set out to fill a perceived hole in what QML/Quick offered, but it took some shortcuts getting there, which were no doubt unavoidable due to various reasons - if nothing else, the times were rather turbulent in the Qt world at the time. The end result of this was not something pretty, when looking at the pile of things like ScrollView regressions, usually a few per release, before even getting to performance concerns.

Unfortunately, of course, since it existed, it got used - despite the shortcomings - though I would say that they likely made themselves very obvious without looking too hard.

At this point, from my perspective, QQC1/QQC2 is largely water under the bridge. I have over the years avoided using QQC1 in several projects as I knew that the performance simply wasn't up to the task without ever trying it "seriously", instead developing custom controls or - now that it is available - using QQC2 where appropriate - so unfortunately, I won't really be able to comment much on that "excitement" except to say that I am happy that QQC2 exists, and I look forward to its continued growth and maturity to fill the gaps with QQC1 where possible and necessary.

This leads me onto topic #2, which is QML's performance itself, and to me, this is a much more interesting topic, and where my own personal concern in the 5.1 -> 5.2 transition came into play. I experienced first-hand a lot of pain in those times and, realistically speaking, I don't think things really started to settle down until some years later.

With the benefit of hindsight, I don't personally think that the engine transition from 5.1 to 5.2 went well, but on the other hand, people are human, and will make mistakes - the important thing is to learn from those mistakes, and not repeat them. As well as that, there were no doubt a number of contributing factors then, similar to QQC1's.

That's quite far in the past, though. Nowadays, there has been a lot of work around the performance area, and it has continued to improve. There's also tracking of performance, to help avoid regressions in the area in future. These are the key reasons I closed the bug -- I think that the message has been heard, improvements have been made, and hopefully things are now consistently heading in the right direction.

You mention qskinny. I think that experimentation is very cool, and it's great that it is working out for your project, and I am already familiar with it, but I'm not too interested in it personally, simply because the QML of "today" (having written a few libraries LOC of QML at this point) generally works well enough for me, and I find the convenience of the language very much worthwhile. I suppose it is also my role to be a cheerleader of sorts for this thing, so there's that. ;-)

Even if our opinions differ though, I'd like to thank you for providing your perspective and story - it is not a surprise to me as I hope I have spelled out given the history of things, but it is interesting to hear. While I hear a lot of reluctance in your mail, I would encourage you to give QML another try in the future, and seeing how it goes for you. If there are things that you find surprising or unpleasant in the performance area, by all means, keep filing issues. Just because that one bug is closed doesn't mean the story is over: performance is a crucial feature in product development, and it is something that we must remain vigilant about, and work on continuously. :-)

Thanks for the mail,
Robin

--
Robin Burchell
***@crimson.no

On Fri, May 25, 2018, at 1:12 PM, Uwe Rathmann wrote:
> Hi all,
>
> this morning I got a notification about
> https://bugreports.qt.io/browse/QTBUG-43096
> being closed. I guess many applications had been hit by this issue, but
> as I was related to the project that created this bug I would like to
> give my summary of what has happened since then:
>
> a)
>
> On the Qt development side a lot of efforts have been made to improve
> the QML problem. I don't want to be disrespectful, but the fact, that
> Controls 1 has finally become deprecated, because of ( IIRC )
> "insolvable performance problems", it is fair say, that those were no
> game changers.
>
> So to me the only step that really matters was introducing Qt/Quick
> Controls 2.
>
> But what makes Controls 2 being superior compared to its predecessor ?
> AFAIK the answer is mostly about doing less QML, achieved by:
>
> - dropping features ( usually desktop related )
> - internally done in C++
>
> Of course this raises the question, why there is no offer for doing more
> in C++ on the application side, when it has been identified as the
> solution for implementing the controls ?
>
> And this is why I'm disappointed about Controls 2. Application code still
> has to be done in QML and when the majority of the GUI code is
> application code the benefits of Controls 2 are limited.
>
> b)
>
> On our side the the decision was made to go back to Qt 5.1, where the
> project is stuck until today.
>
> Almost all developers of the original team are gone - none
> of them recommending QML as technology for further projects. Even worse
> - some of them explicitly mentioned QML being a reason for leaving.
>
> So for the next generation of our product we started to implement our
> own framework on top of the C++ part of Qt/Quick (
> https://github.com/uwerat/qskinny ). Our user interface today consists
> about ~200K lines of code ( pure C++ ) and so far I can say that the
> typical problems of having a bad startup performance or the heavy memory
> footprint simple don't exist.
>
> Unfortunately we still have to maintain our previous product written in
> QML for many years. Maybe we can migrate it step by step to our new
> framework.
>
> With all respect,
> Uwe
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
Simon Hausmann
2018-05-25 13:20:48 UTC
Permalink
Hi,


And to add what Robin said, solely focused on the task in question that was closed:


I ran benchmarks comparing a release build of 5.12 against 5.1.1 and ran the benchmark mentioned in the task, where Qt 5.12 came out in average faster by a factor of 4.


More details as well as the concrete run results are in the JIRA ticket. I do consider the concret QML object instantiation performance decadence to be resolved.



Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org> on behalf of Robin Burchell <***@crimson.no>
Sent: Friday, May 25, 2018 2:30:05 PM
To: ***@qt-project.org
Subject: Re: [Development] QTBUG-43096 - QML instantiation performance decadence

Hi Uwe,

I had predicted a response, so this mail comes as no surprise to me :)

Personal opinions on various things ahead, the reader may disagree with me, that's perfectly normal and OK.

From my own perspective, I think Controls 1 was a well-intentioned mistake. It set out to fill a perceived hole in what QML/Quick offered, but it took some shortcuts getting there, which were no doubt unavoidable due to various reasons - if nothing else, the times were rather turbulent in the Qt world at the time. The end result of this was not something pretty, when looking at the pile of things like ScrollView regressions, usually a few per release, before even getting to performance concerns.

Unfortunately, of course, since it existed, it got used - despite the shortcomings - though I would say that they likely made themselves very obvious without looking too hard.

At this point, from my perspective, QQC1/QQC2 is largely water under the bridge. I have over the years avoided using QQC1 in several projects as I knew that the performance simply wasn't up to the task without ever trying it "seriously", instead developing custom controls or - now that it is available - using QQC2 where appropriate - so unfortunately, I won't really be able to comment much on that "excitement" except to say that I am happy that QQC2 exists, and I look forward to its continued growth and maturity to fill the gaps with QQC1 where possible and necessary.

This leads me onto topic #2, which is QML's performance itself, and to me, this is a much more interesting topic, and where my own personal concern in the 5.1 -> 5.2 transition came into play. I experienced first-hand a lot of pain in those times and, realistically speaking, I don't think things really started to settle down until some years later.

With the benefit of hindsight, I don't personally think that the engine transition from 5.1 to 5.2 went well, but on the other hand, people are human, and will make mistakes - the important thing is to learn from those mistakes, and not repeat them. As well as that, there were no doubt a number of contributing factors then, similar to QQC1's.

That's quite far in the past, though. Nowadays, there has been a lot of work around the performance area, and it has continued to improve. There's also tracking of performance, to help avoid regressions in the area in future. These are the key reasons I closed the bug -- I think that the message has been heard, improvements have been made, and hopefully things are now consistently heading in the right direction.

You mention qskinny. I think that experimentation is very cool, and it's great that it is working out for your project, and I am already familiar with it, but I'm not too interested in it personally, simply because the QML of "today" (having written a few libraries LOC of QML at this point) generally works well enough for me, and I find the convenience of the language very much worthwhile. I suppose it is also my role to be a cheerleader of sorts for this thing, so there's that. ;-)

Even if our opinions differ though, I'd like to thank you for providing your perspective and story - it is not a surprise to me as I hope I have spelled out given the history of things, but it is interesting to hear. While I hear a lot of reluctance in your mail, I would encourage you to give QML another try in the future, and seeing how it goes for you. If there are things that you find surprising or unpleasant in the performance area, by all means, keep filing issues. Just because that one bug is closed doesn't mean the story is over: performance is a crucial feature in product development, and it is something that we must remain vigilant about, and work on continuously. :-)

Thanks for the mail,
Robin

--
Robin Burchell
***@crimson.no

On Fri, May 25, 2018, at 1:12 PM, Uwe Rathmann wrote:
> Hi all,
>
> this morning I got a notification about
> https://bugreports.qt.io/browse/QTBUG-43096
> being closed. I guess many applications had been hit by this issue, but
> as I was related to the project that created this bug I would like to
> give my summary of what has happened since then:
>
> a)
>
> On the Qt development side a lot of efforts have been made to improve
> the QML problem. I don't want to be disrespectful, but the fact, that
> Controls 1 has finally become deprecated, because of ( IIRC )
> "insolvable performance problems", it is fair say, that those were no
> game changers.
>
> So to me the only step that really matters was introducing Qt/Quick
> Controls 2.
>
> But what makes Controls 2 being superior compared to its predecessor ?
> AFAIK the answer is mostly about doing less QML, achieved by:
>
> - dropping features ( usually desktop related )
> - internally done in C++
>
> Of course this raises the question, why there is no offer for doing more
> in C++ on the application side, when it has been identified as the
> solution for implementing the controls ?
>
> And this is why I'm disappointed about Controls 2. Application code still
> has to be done in QML and when the majority of the GUI code is
> application code the benefits of Controls 2 are limited.
>
> b)
>
> On our side the the decision was made to go back to Qt 5.1, where the
> project is stuck until today.
>
> Almost all developers of the original team are gone - none
> of them recommending QML as technology for further projects. Even worse
> - some of them explicitly mentioned QML being a reason for leaving.
>
> So for the next generation of our product we started to implement our
> own framework on top of the C++ part of Qt/Quick (
> https://github.com/uwerat/qskinny ). Our user interface today consists
> about ~200K lines of code ( pure C++ ) and so far I can say that the
> typical problems of having a bad startup performance or the heavy memory
> footprint simple don't exist.
>
> Unfortunately we still have to maintain our previous product written in
> QML for many years. Maybe we can migrate it step by step to our new
> framework.
>
> With all respect,
> Uwe
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
Uwe Rathmann
2018-05-31 07:21:00 UTC
Permalink
Hi Simon,

> I ran benchmarks comparing a release build of 5.12 against 5.1.1 and ran
> the benchmark mentioned in the task, where Qt 5.12 came out in average
> faster by a factor of 4.

Christophers comment in the JIRA ticket raises some questions concerning
the correctness of those benchmarks.

Would you be so kind to clarify how far we can trust in these numbers ?

Uwe
Chris Adams
2018-05-31 07:48:53 UTC
Permalink
On Thu, May 31, 2018 at 5:21 PM, Uwe Rathmann <***@tigertal.de> wrote:
> Hi Simon,
>
>> I ran benchmarks comparing a release build of 5.12 against 5.1.1 and ran
>> the benchmark mentioned in the task, where Qt 5.12 came out in average
>> faster by a factor of 4.
>
> Christophers comment in the JIRA ticket raises some questions concerning
> the correctness of those benchmarks.
>
> Would you be so kind to clarify how far we can trust in these numbers ?

I did have a couple of questions about that particular benchmark
result, but that doesn't mean that the conclusion is incorrect.

It's important to note that the issue may lie in the original numbers,
as the library metrics test previously used some hand-rolled methods
to discard outliers and perform an average, and worked on wall time
rather than cpu ticks - a method which may very well have been wrong
(and that would be entirely my fault).

Also, it is worth pointing out that recently a considerable effort has
been made to improve the benchmarking of all stages of QtQuick
applications (from the JS side of things, to the QML compiler side of
things, to the scene graph side of things), as the grafana and
qmlbench etc tracking proves. Performance regressions are now being
caught, and performance metrics are easily visible, thanks to those
efforts, and that is definitely have a very positive effect on
performance outcomes for everyone.

FWIW I am certain that the QML engine in Qt 5.12 will indeed perform
better than it did in Qt 5.1 days (or any other version of Qt) because
the people working most closely with the engine and the people working
most closely with QtQuick both believe it to be so, and I trust their
judgement.

Best regards,
Chris.
Tomasz Olszak
2018-06-04 08:58:25 UTC
Permalink
Hi Uwe,

I quickly reviewed QSkinny and it really nicely exposes C++ to Qml. I can't
see however, how you made e.g. QskVariant::stops readable from Qml. Writing
stops is possible due to QMetaType::registerConvertes, but how you can
iterate overs stop from Qml?

Thanks in advance for clarification,
Tomek

PS: I also tried to have the same implementation for C++ and Qt Qml and now
some classes contains duplicated getters/setters (QVariantList instead of
QVector<C++Type>).

2018-05-31 9:48 GMT+02:00 Chris Adams <***@qinetic.com.au>:

> On Thu, May 31, 2018 at 5:21 PM, Uwe Rathmann <***@tigertal.de>
> wrote:
> > Hi Simon,
> >
> >> I ran benchmarks comparing a release build of 5.12 against 5.1.1 and ran
> >> the benchmark mentioned in the task, where Qt 5.12 came out in average
> >> faster by a factor of 4.
> >
> > Christophers comment in the JIRA ticket raises some questions concerning
> > the correctness of those benchmarks.
> >
> > Would you be so kind to clarify how far we can trust in these numbers ?
>
> I did have a couple of questions about that particular benchmark
> result, but that doesn't mean that the conclusion is incorrect.
>
> It's important to note that the issue may lie in the original numbers,
> as the library metrics test previously used some hand-rolled methods
> to discard outliers and perform an average, and worked on wall time
> rather than cpu ticks - a method which may very well have been wrong
> (and that would be entirely my fault).
>
> Also, it is worth pointing out that recently a considerable effort has
> been made to improve the benchmarking of all stages of QtQuick
> applications (from the JS side of things, to the QML compiler side of
> things, to the scene graph side of things), as the grafana and
> qmlbench etc tracking proves. Performance regressions are now being
> caught, and performance metrics are easily visible, thanks to those
> efforts, and that is definitely have a very positive effect on
> performance outcomes for everyone.
>
> FWIW I am certain that the QML engine in Qt 5.12 will indeed perform
> better than it did in Qt 5.1 days (or any other version of Qt) because
> the people working most closely with the engine and the people working
> most closely with QtQuick both believe it to be so, and I trust their
> judgement.
>
> Best regards,
> Chris.
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
Uwe Rathmann
2018-06-04 17:43:44 UTC
Permalink
Hi Tomek,

> I quickly reviewed QSkinny and it really nicely exposes C++ to Qml. I
> can't see however, how you made e.g. QskVariant::stops readable from
> Qml. Writing stops is possible due to QMetaType::registerConvertes, but
> how you can iterate overs stop from Qml?

Don't know either, but I'm not the right person to ask when it comes to
JavaScript related issues.

> PS: I also tried to have the same implementation for C++ and Qt Qml and
> now some classes contains duplicated getters/setters (QVariantList
> instead of QVector<C++Type>).

Hope it is o.k. to throw in some ideas/experiences, but as my work is not
part of the qt-project I don't want to to misuse this mailing list.

But if you ( or anyone else ) likes to discuss in more depth what I'm
doing you can always contact me of the list.

ciao,
Uwe
Tomasz Olszak
2018-07-23 10:52:46 UTC
Permalink
Hi,
I'm resurrecting this thread because it showed me that I can do more
with QML (registerConverters).
The only missing part was to allow developer to register converter
from his custom metatype to QML. I often ended up with making 2
properties e.g:

QList<Gadget> cppProperty
QVariantList qmlProperty

the API was ugly, etc.

Then I realized that if we already handle QVariant properly in QML
then why not to allow app developer to register converter to e.g.
QList<Gadget> -> QVariant
And use it in QML engine.

I made this simple patch and tested that it works, and is totally
enough for my needs. It make my API clean, If I need big performance I
do not use QList but rather create model.
However for simple, UI, cases it s a great benefit.

https://codereview.qt-project.org/#/c/235051

I haven't spent much time on it, probably data from "void *data =
QMetaType::create(property.propType());" needs to be deleted after
conversion. I is:f you find the solution acceptable I can polish it
with your help.

Now the main question is: what's wrong with this approach? Would it
break QML compiler? I don't see it having big performance issues
because a lot of app developer does the same but just inside their app
code.

pon., 4 cze 2018 o 19:46 Uwe Rathmann <***@tigertal.de> napisał(a):
>
> Hi Tomek,
>
> > I quickly reviewed QSkinny and it really nicely exposes C++ to Qml. I
> > can't see however, how you made e.g. QskVariant::stops readable from
> > Qml. Writing stops is possible due to QMetaType::registerConvertes, but
> > how you can iterate overs stop from Qml?
>
> Don't know either, but I'm not the right person to ask when it comes to
> JavaScript related issues.
>
> > PS: I also tried to have the same implementation for C++ and Qt Qml and
> > now some classes contains duplicated getters/setters (QVariantList
> > instead of QVector<C++Type>).
>
> Hope it is o.k. to throw in some ideas/experiences, but as my work is not
> part of the qt-project I don't want to to misuse this mailing list.
>
> But if you ( or anyone else ) likes to discuss in more depth what I'm
> doing you can always contact me of the list.
>
> ciao,
> Uwe
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
Uwe Rathmann
2018-05-25 14:31:30 UTC
Permalink
Hi Robin,

> From my own perspective, I think Controls 1 was a well-intentioned ...

Agreed and to be honest I'm really impressed about what was doable in QML,
but it also showed where its limitations are.

But at the time, when Controls 2 has been started everything was on the
table and - at least from the outside - it looked like a comfortable
situation for making good decisions. And this is what I had expected to
happen:

a) a solid C++ API with the same quality we are used
from all other Qt modules. Then the majority of the API is already
available for QML by the standard mechanisms of the Qt/MetaObject system.

b) a thin layer on top to make the QML API feature complete.

Unfortunately I never noticed any indication pointing into the direction
of a better C++ support. In fact the opposite happened: even the very
base class of all QC 2 controls is not part of the public API !

> These are the key reasons I closed the bug -- I think
> that the message has been heard, improvements have been made, and
> hopefully things are now consistently heading in the right direction.

The stupid fact is that QML always comes at a cost. Trying to reduce
these cost has been successfully done and any further improvements are
welcome, but: as long as there is no clear separation between the Qt/
Quick graphic stack and QML I disagree, that the "right direction" has
already been found.

> You mention qskinny. I think that experimentation is very cool, and it's
> great that it is working out for your project, and I am already familiar
> with it, but I'm not too interested in it personally, simply because the
> QML of "today" (having written a few libraries LOC of QML at this point)
> generally works well enough for me, and I find the convenience of the
> language very much worthwhile.

QSkinny is not about QML vs. C++ - it supports both, and some of the
provided examples are in QML.

The reasons, why we are not using QML is because we decided so. And this
is the opposite to our previous version, where we made the decision for
QML because we had to.

--

Maybe a word on my intentions about QSkinny:

in the first place it is supposed to be the platform for the products of
our company ( being in the automotive industry ). So writing the docs,
polishing the skins ( = themes ) or completing the set of controls -
steps that should be done to make the project more accessible - do not
have the priority they deserve.

But I believe, that it is a good starting point to make more out of the
Qt/Quick graphic stack as what we see today. And if in the end nobody
else is interested ( in using or contributing ) it is good enough to
demonstrate what is possible.

Uwe
Robin Burchell
2018-05-25 19:55:29 UTC
Permalink
On Fri, May 25, 2018, at 4:31 PM, Uwe Rathmann wrote:
> But at the time, when Controls 2 has been started everything was on the
> table and - at least from the outside - it looked like a comfortable
> situation for making good decisions. And this is what I had expected to
> happen:

What happens is only what there are enough time and resources to do, plus a direction to do it in the first place. It might be that you had attempted to drive some of this work yourself (or yourselves), I don't know - but I didn't see any discussion about it on this list that I recall, and I don't recall anything hitting codereview either, so I have to say that from the perspective of the project, I can't see how you could really expect this to happen.

> Unfortunately I never noticed any indication pointing into the direction
> of a better C++ support. In fact the opposite happened: even the very
> base class of all QC 2 controls is not part of the public API !

Why does it need to be? I have never needed to subclass QQuickControl, personally, so I have never brought this topic up.

Assuming you have a valid reason, then I would present my next problem with that: it's probably not mature enough. QQC2 is only three years old, and it is (still) going through quite a lot of change that is often likely not ABI compatible[1]. Sure, it's often _possible_ to work with this stuff in a backwards-compatible fashion, but that comes at a strong cost, which then requires answering: does the cost of having to work in such a manner justify making it public? I would tend to suggest no in that particular case from what I know right now.

> The stupid fact is that QML always comes at a cost. Trying to reduce
> these cost has been successfully done and any further improvements are
> welcome, but: as long as there is no clear separation between the Qt/
> Quick graphic stack and QML I disagree, that the "right direction" has
> already been found.

There is a cost, yes. But I would say it's more a cost/benefit tradeoff. Faster prototyping and development cycles at a cost of requiring some of your resources to munch on. And, well, this problem isn't just limited to QML or QtQuick- if you want to run Qt as it exists today on a lightbulb, you're probably getting something wrong in your architectural design. ;-)

Anyway, wrt direction, I assume you are hinting at a scenegraph that is less tied to QtQuick. If you are volunteering to help engineer such a separation in a way that is maintainable in the long term, and doesn't negatively impact performance of the graphics stack's consumer (QtQuick), then I have no objections personally, though I'm not really the right person to talk to. I would suggest coming up with specific proposals for what you want done, talking them over on this list, and then working on patches assuming there are no objections.

But if you are asking me personally to separate the scenegraph out, then I have no interest in doing so. As I said, I am happy with QML and QtQuick in their present form (with hopefully indefinite iterations to improve it over time, of course).

[1]: This does bring me to something that I do find unfortunate: API stability is a lot easier to promise than ABI stability. I can imagine a world in which we would have a public _API_ for more things than we do nowadays, but I am hesitant to contemplate that too much, because it ties our hands in changing the implementation a lot wrt ABI compatibility.
Jean-Michaël Celerier
2018-05-26 06:38:27 UTC
Permalink
> Why does it need to be? I have never needed to subclass QQuickControl,
personally, so I have never brought this topic up.

It's not about subclassing QQuickControl, it's about running code without a
JIT / interpreter. Even if the cost in startup time and performance is
minimal, it is not as fast as raw C++ code - and there's nothing wrong with
wanting Qt to run on a lightbulb... some lightbulbs today have better CPUs
than the ones Qt was originally developed on.

In addition, there's something in which Qt Quick fails quite flat: any kind
of UI that revolves around graphs with a lot of objects - stuff with which
QGraphicsView is perfectly at ease. Look for instance at the model editor
in Qt Creator : they went - rightly - with QGraphicsView.

I tried to port my software (https://github.com/OSSIA/score) to Qt Quick
twice but stuff like showing hundreds of text elements updated concurrently
killed performance, while QGraphicsView has no problem blitting them like
there's no tomorrow. And that's with Qt Quick having a much more restricted
API than QGraphicsScene/View. But of course I'm sad since I have to
reimplement basic widgets in QGraphics* manually and cannot use the pretty
QQC2 ones :p

Even the latest innovation, QML Shapes, is beaten in performance by
existing solutions :
http://kgronholm.blogspot.fr/2017/12/qt-510-rendering-benchmarks.html that
in addition also provide a C++ API.



-------
Jean-Michaël Celerier
http://www.jcelerier.name

On Fri, May 25, 2018 at 9:55 PM, Robin Burchell <***@crimson.no>
wrote:

> On Fri, May 25, 2018, at 4:31 PM, Uwe Rathmann wrote:
> > But at the time, when Controls 2 has been started everything was on the
> > table and - at least from the outside - it looked like a comfortable
> > situation for making good decisions. And this is what I had expected to
> > happen:
>
> What happens is only what there are enough time and resources to do, plus
> a direction to do it in the first place. It might be that you had attempted
> to drive some of this work yourself (or yourselves), I don't know - but I
> didn't see any discussion about it on this list that I recall, and I don't
> recall anything hitting codereview either, so I have to say that from the
> perspective of the project, I can't see how you could really expect this to
> happen.
>
> > Unfortunately I never noticed any indication pointing into the direction
> > of a better C++ support. In fact the opposite happened: even the very
> > base class of all QC 2 controls is not part of the public API !
>
> Why does it need to be? I have never needed to subclass QQuickControl,
> personally, so I have never brought this topic up.
>
> Assuming you have a valid reason, then I would present my next problem
> with that: it's probably not mature enough. QQC2 is only three years old,
> and it is (still) going through quite a lot of change that is often likely
> not ABI compatible[1]. Sure, it's often _possible_ to work with this stuff
> in a backwards-compatible fashion, but that comes at a strong cost, which
> then requires answering: does the cost of having to work in such a manner
> justify making it public? I would tend to suggest no in that particular
> case from what I know right now.
>
> > The stupid fact is that QML always comes at a cost. Trying to reduce
> > these cost has been successfully done and any further improvements are
> > welcome, but: as long as there is no clear separation between the Qt/
> > Quick graphic stack and QML I disagree, that the "right direction" has
> > already been found.
>
> There is a cost, yes. But I would say it's more a cost/benefit tradeoff.
> Faster prototyping and development cycles at a cost of requiring some of
> your resources to munch on. And, well, this problem isn't just limited to
> QML or QtQuick- if you want to run Qt as it exists today on a lightbulb,
> you're probably getting something wrong in your architectural design. ;-)
>
> Anyway, wrt direction, I assume you are hinting at a scenegraph that is
> less tied to QtQuick. If you are volunteering to help engineer such a
> separation in a way that is maintainable in the long term, and doesn't
> negatively impact performance of the graphics stack's consumer (QtQuick),
> then I have no objections personally, though I'm not really the right
> person to talk to. I would suggest coming up with specific proposals for
> what you want done, talking them over on this list, and then working on
> patches assuming there are no objections.
>
> But if you are asking me personally to separate the scenegraph out, then I
> have no interest in doing so. As I said, I am happy with QML and QtQuick in
> their present form (with hopefully indefinite iterations to improve it over
> time, of course).
>
> [1]: This does bring me to something that I do find unfortunate: API
> stability is a lot easier to promise than ABI stability. I can imagine a
> world in which we would have a public _API_ for more things than we do
> nowadays, but I am hesitant to contemplate that too much, because it ties
> our hands in changing the implementation a lot wrt ABI compatibility.
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
Thiago Macieira
2018-05-26 13:15:00 UTC
Permalink
On Saturday, 26 May 2018 03:38:27 -03 Jean-Michaël Celerier wrote:
> It's not about subclassing QQuickControl, it's about running code without a
> JIT / interpreter. Even if the cost in startup time and performance is
> minimal, it is not as fast as raw C++ code - and there's nothing wrong with
> wanting Qt to run on a lightbulb... some lightbulbs today have better CPUs
> than the ones Qt was originally developed on.

I know you're making an exaggeration here for the sake of the argument, but
it's not correct.

First, Qt has considerably grown since 1.0. Just compare the size of the
downloads from Qt 1.4 (available somewhere in download.qt.io, see Paul's blog)
to 5.11. QtCore alone, today, is multiple times the size of the full Qt of
back then.

Second, no, Qt has never run on a CPU as tiny as you can find today on
microcontrollers being deployed for IoT today. Those are still measured in
tens of kilobytes of RAM with maybe a hundred kilobyte of flash storage. The
only indicator that is comparable to the mainstay computers of 20 years ago is
the clock: the microcontrollers run at tens of MHz, which is what the original
Pentium from 1991 did (60 MHz).

You may be thinking of processors as powerful as a Raspberry Pi Zero. Trust
me, that is NOT what you would deploy to a light bulb, temperature sensor,
humidity sensor, etc. You wouldn't even find that on a controller device with
a simple screen, like a thermostat similar to the Google Nest: a system like
you find on routers today (8-32 MB of flash storage, 32-128 MB of RAM, a CPU
running at 200-600 MHz) more than suffices.

Qt *could* run at the higher end of those, with a lot of compromises to make
it fit. Which is why I don't think Qt has a role to play in these types of
devices. Instead, Qt is far more likely to play in the industrial segment
where devices need complex Human Machine Interfaces (HMI) and monitoring
capabilities. Devices are also far more costly, since they aren't going for
mass-market strategies.

Finally, there's one more segment Qt could play, but it doesn't exist yet:
microservices. If we start seeing controllers like I described replaced by a
bigger device capable of installing and running multiple services,
configurable by the user, then some of those could be Qt. Those microservices
are likely to simply be Linux containers, so you should be expecting the host
device to be like a Raspberry Pi or a low-end Intel Atom CPU with 1 GB of RAM
or so.

[It goes without saying that Qt could be used for digital signage, but it's a
stretch to call those IoT]

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Uwe Rathmann
2018-05-26 09:20:09 UTC
Permalink
Hi Robin,

> Why does it need to be? I have never needed to subclass QQuickControl,
> personally, so I have never brought this topic up.

For the same reason all other controls from QC2 do subclass it. If you
want to participate in mechanisms ( like font/locale/palette propagation
) that are implemented in this base class, you have to.

> There is a cost, yes. But I would say it's more a cost/benefit tradeoff.
> Faster prototyping and development cycles at a cost of requiring some of
> your resources to munch on.

Please allow me not to respond: I would like to avoid ending up in yet
another QML vs. C++ discussion.

> Anyway, wrt direction, I assume you are hinting at a scenegraph that is
> less tied to QtQuick.

No, the scene graph is already a standalone module with a well designed
public API: many thanks to the authors. Its API could be more comfortable
and the existing set of nodes is underfeatured, but in general I have not
much to complain.

Almost everything is about the C++ classes of the various Qt/Quick
modules. The majority of them is designed with having QML as the one and
only use case in mind.

I'm also not happy about how the scene graph is used inside of those
classes, because it substantially contributes to the memory and startup
performance problems of Qt/Quick. It took me some tome to get those
things under control, but in the end it was possible without having to
patch Qt code itself.

> If you are volunteering ...

I am - and you can already see more than 50K lines of code from my
efforts.

Uwe
Ville Voutilainen
2018-05-26 13:07:46 UTC
Permalink
On 26 May 2018 at 12:20, Uwe Rathmann <***@tigertal.de> wrote:
> Hi Robin,
>
>> Why does it need to be? I have never needed to subclass QQuickControl,
>> personally, so I have never brought this topic up.
>
> For the same reason all other controls from QC2 do subclass it. If you
> want to participate in mechanisms ( like font/locale/palette propagation
> ) that are implemented in this base class, you have to.
>
>> There is a cost, yes. But I would say it's more a cost/benefit tradeoff.
>> Faster prototyping and development cycles at a cost of requiring some of
>> your resources to munch on.
>
> Please allow me not to respond: I would like to avoid ending up in yet
> another QML vs. C++ discussion.

I think it makes perfect sense for many reasons to strive for exposing
the QC2/QML/etc. API to
C++ applications, and that that's something we should certainly do.
There are very reasonable
user scenarios and business cases where that would be desirable, as
the trade-offs mentioned
are on the scale from unpalatable to undesirable to unattractive.
Uwe Rathmann
2018-05-25 19:14:35 UTC
Permalink
On Fri, 25 May 2018 14:30:05 +0200, Robin Burchell wrote:

> I have over the years avoided using QQC1 in several projects as
> I knew that the performance simply wasn't up to the task without ever
> trying it "seriously", instead developing custom controls ...

Please let me give a detailed answer to this one:

On the Qt Conn 2016 Andrew ( Knight ) presented our very first results,
when comparing 4 different implementations of an average button.

a) a button from Quick Controls 1
b) a button from Quick Controls 2
c) a custom button composed in QML ( this is your approach )
d) a button from QSkinny

All implementations have been done in QML with very similar code.

Unfortunately the presentation has not been recorded, but out of my
memory one of our statistics was:

a) > 30 QObjects
b + c ) 7 QObjects
d) 1 QObject

The reason why QSkinny is more lightweight is because it does scene graph
node composition, where all other implementations are composing more
heavy Quick items.

( But we also noticed stuff like that: QQuickGradient is a QObject and
even QQuickGradientStop is one. So for the definition of a gradient with
2 colors you need 3 QObjects: > 400 bytes. These little things could
easily being fixed by using Q_GADGET - but obviously nobody cares. )

--

Another example I can give is related to new code: the page indicator
from Quick Controls 2. IMHO all what should be needed to describe such a
control is the number of the bullets, the index of the current one, the
shape of the bullets and maybe some color information - all in all maybe
~50 bytes.

But the way how it is implemented is having a Quick Item for each bullet.
IIRC an item has a minimum of 320 bytes ( usually more ) and has an extra
transform node on top of its paint node. So we end up with something like
n * 400 instead of ~50. Might be interesting to count the exact numbers
being consumed with the existing styles - I would expect to end up with
something scary.

I don't want to insist too much on the page indicator example as this is
usually not a control that is instantiated many times in the same
application. But to me it is symptomatic and you find a similar situation
almost everywhere.

Uwe
Robin Burchell
2018-05-25 20:35:58 UTC
Permalink
On Fri, May 25, 2018, at 9:14 PM, Uwe Rathmann wrote:
> On the Qt Conn 2016 Andrew ( Knight ) presented our very first results,
> when comparing 4 different implementations of an average button.
>
> a) a button from Quick Controls 1
> b) a button from Quick Controls 2
> c) a custom button composed in QML ( this is your approach )
> d) a button from QSkinny
>
> All implementations have been done in QML with very similar code.
>
> Unfortunately the presentation has not been recorded, but out of my
> memory one of our statistics was:
>
> a) > 30 QObjects
> b + c ) 7 QObjects
> d) 1 QObject

I'm familiar with numbers like that. I've come up with many similar ones myself in the past. The first point I would make in reply, though, is that the convenience of creating code with a/b/c are going to be significantly better in my experience.

And in addition, nothing (except the lack of a need to _actually_ go this far) stops me from writing a button using QSGNode instances today, without any use of private API and similarly avoiding many of those object allocations.

The one feature that would be a problem would be a missing public text node, which would mean I'd have to resort to a QQmlComponent with a Text item in it to set my label. Off the top of my head, that makes three QObjects, for the record: a QQuickItem for the button, a QObject (really a QQuickTextItem) from the component, and QQmlComponent itself, though that last one can be shared between buttons.

Adding a public text node would be nice if we wanted to make it a single QObject, but doesn't justify creating a whole new framework to me, given it's perfectly possible with the API of QtQuick today, and there is plenty of precedent (and demand) for it.

(And no, I don't think that just making QQuickTextNode public is the answer. That is a very, very heavy set of classes, it really needs some thought and cleanup applied first I think, alas, I don't know of anyone working on it today...)

> ( But we also noticed stuff like that: QQuickGradient is a QObject and
> even QQuickGradientStop is one. So for the definition of a gradient with
> 2 colors you need 3 QObjects: > 400 bytes. These little things could
> easily being fixed by using Q_GADGET - but obviously nobody cares. )

It's not that nobody cares, it's that you can't actually do that without breaking code that probably[1] exists in the real world. Let's take another good example from the top of my head: Item::anchors. Behind the scenes, it's implemented as a QQuickAnchors, which is a QObject. Let's turn it into a Q_GADGET, and we're done, right?

Well, not quite, because now any code that does this:

anchors { onLeftChanged { ... } }

or this:

this.anchors.leftChanged.connect(function() { ... })

or in the C++ world:

connect(myItem->anchors(), &QQuickAnchors::leftChanged, ...

... will break, since Q_GADGET doesn't have signals - so it's simply not equivilent.

It's nice to contemplate this sort of stuff, of course, and I'd love to see common features like anchors made cheaper (really, gradients aren't anywhere near as common, at least for the sake of my eyeballs I sure hope so), but doing so requires a careful approach, and probably a good chunk of grunt-work and magic that doesn't exist right now to make it actually happen, which is likely why it hasn't happened yet. Suggestions of how (or better still, patches), most certainly welcome.

[1]: almost certainly. my personal rule is: if there is API for it, someone will misuse it in the most awful way possible to make your life hell with it, somehow. I think one has to have a love-hate relationship with users, you can't live without them, but my god you wish you could sometimes ;-).
Uwe Rathmann
2018-05-26 10:30:11 UTC
Permalink
On Fri, 25 May 2018 22:35:58 +0200, Robin Burchell wrote:

> The first point I would make in reply, though, is
> that the convenience of creating code with a/b/c are going to be
> significantly better in my experience.

Code for d) look like this:
https://github.com/uwerat/qskinny/blob/master/examples/buttons/buttons.qml

IMHO the code for a/b would be very similar, the only one that requires
more work would be c as you need extra code for creating the button
itself.

> Let's take
> another good example from the top of my head: Item::anchors. Behind the
> scenes, it's implemented as a QQuickAnchors, which is a QObject. Let's
> turn it into a Q_GADGET, and we're done, right?

No, but please let's stay with gradients, where the answer is yes.

QSkinny offers this class to expose gradients to QML: https://github.com/
uwerat/qskinny/blob/master/src/common/QskGradient.h

Now when having an control with a property like this:

class MyRectangle : public QQuickItem
{
Q_OBJECT

Q_PROPERTY( QskGradient gradient READ gradient
WRITE setGradient RESET resetGradient NOTIFY gradientChanged )

...
};

you can write your QML code this way:

MyRectangle
{
gradient {
orientation: "Vertical"

stops: [
{ position: 0.0, color: "MediumAquamarine" },
{ position: 0.5, color: "..." },
{ position: 1.0, color: "DarkSeaGreen" },
]
}
}

The equivalent code offered by Qt/Quick needs 4 QObjects - for each
instance of an item. So when having 100 rectangles these are 400 QObjects
- good for nothing.

Uwe
Aleksey Kontsevich
2018-05-26 10:36:23 UTC
Permalink
_______________________________________________
Development mailing list
***@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development
Simon Hausmann
2018-05-26 12:05:38 UTC
Permalink
Hi,


Jêdrzej had a beautiful proof of concept at some point for QObject to combine the object and d-pointer allocation into one.


That's where I had the idea that perhaps this idea could be extended all the way to QML, so that the instantiation of a .qml file would collect all object and d-pointer sizes at type compilation time and use a bumper pointer allocator during instantiation (assuming that we can verify upfront that the types support it).


The consequence would be one libc malloc for all objects per .qml file and pointer based APIs like anchors or gradients would involve no data copying at all, as opposed to value based gadget APIs.


This would require a static QObject parent-hierarchy and make a few other assumptions, but as long as they are the common case and can be detected, I think there are ways of making QtQuick elements instantiate faster and use less memory.




Simon


P.S.: Are you sure the stops: [ ... ] assignment works?

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org> on behalf of Uwe Rathmann <***@tigertal.de>
Sent: Saturday, May 26, 2018 12:30:11 PM
To: ***@qt-project.org
Subject: Re: [Development] QTBUG-43096 - QML instantiation performance decadence

On Fri, 25 May 2018 22:35:58 +0200, Robin Burchell wrote:

> The first point I would make in reply, though, is
> that the convenience of creating code with a/b/c are going to be
> significantly better in my experience.

Code for d) look like this:
https://github.com/uwerat/qskinny/blob/master/examples/buttons/buttons.qml

IMHO the code for a/b would be very similar, the only one that requires
more work would be c as you need extra code for creating the button
itself.

> Let's take
> another good example from the top of my head: Item::anchors. Behind the
> scenes, it's implemented as a QQuickAnchors, which is a QObject. Let's
> turn it into a Q_GADGET, and we're done, right?

No, but please let's stay with gradients, where the answer is yes.

QSkinny offers this class to expose gradients to QML: https://github.com/
uwerat/qskinny/blob/master/src/common/QskGradient.h

Now when having an control with a property like this:

class MyRectangle : public QQuickItem
{
Q_OBJECT

Q_PROPERTY( QskGradient gradient READ gradient
WRITE setGradient RESET resetGradient NOTIFY gradientChanged )

...
};

you can write your QML code this way:

MyRectangle
{
gradient {
orientation: "Vertical"

stops: [
{ position: 0.0, color: "MediumAquamarine" },
{ position: 0.5, color: "..." },
{ position: 1.0, color: "DarkSeaGreen" },
]
}
}

The equivalent code offered by Qt/Quick needs 4 QObjects - for each
instance of an item. So when having 100 rectangles these are 400 QObjects
- good for nothing.

Uwe
Jean-Michaël Celerier
2018-05-26 12:12:25 UTC
Permalink
> Jędrzej had a beautiful proof of concept at some point for QObject to
combine the object and d-pointer allocation into one.
If only there was a way to be able to use Qt without all the PIMPLing and
just have QObjectPrivate be a "normal" QObject member !




-------
Jean-Michaël Celerier
http://www.jcelerier.name

On Sat, May 26, 2018 at 2:05 PM, Simon Hausmann <***@qt.io>
wrote:

> Hi,
>
>
> Jędrzej had a beautiful proof of concept at some point for QObject to
> combine the object and d-pointer allocation into one.
>
>
> That's where I had the idea that perhaps this idea could be extended all
> the way to QML, so that the instantiation of a .qml file would collect all
> object and d-pointer sizes at type compilation time and use a bumper
> pointer allocator during instantiation (assuming that we can verify upfront
> that the types support it).
>
>
> The consequence would be one libc malloc for all objects per .qml file and
> pointer based APIs like anchors or gradients would involve no data copying
> at all, as opposed to value based gadget APIs.
>
>
> This would require a static QObject parent-hierarchy and make a few other
> assumptions, but as long as they are the common case and can be detected, I
> think there are ways of making QtQuick elements instantiate faster and use
> less memory.
>
>
>
>
> Simon
>
>
> P.S.: Are you sure the stops: [ ... ] assignment works?
> ------------------------------
> *From:* Development <development-bounces+simon.hausmann=
> ***@qt-project.org> on behalf of Uwe Rathmann <***@tigertal.de>
> *Sent:* Saturday, May 26, 2018 12:30:11 PM
> *To:* ***@qt-project.org
> *Subject:* Re: [Development] QTBUG-43096 - QML instantiation performance
> decadence
>
> On Fri, 25 May 2018 22:35:58 +0200, Robin Burchell wrote:
>
> > The first point I would make in reply, though, is
> > that the convenience of creating code with a/b/c are going to be
> > significantly better in my experience.
>
> Code for d) look like this:
> https://github.com/uwerat/qskinny/blob/master/examples/buttons/buttons.qml
>
> IMHO the code for a/b would be very similar, the only one that requires
> more work would be c as you need extra code for creating the button
> itself.
>
> > Let's take
> > another good example from the top of my head: Item::anchors. Behind the
> > scenes, it's implemented as a QQuickAnchors, which is a QObject. Let's
> > turn it into a Q_GADGET, and we're done, right?
>
> No, but please let's stay with gradients, where the answer is yes.
>
> QSkinny offers this class to expose gradients to QML: https://github.com/
> uwerat/qskinny/blob/master/src/common/QskGradient.h
>
> Now when having an control with a property like this:
>
> class MyRectangle : public QQuickItem
> {
> Q_OBJECT
>
> Q_PROPERTY( QskGradient gradient READ gradient
> WRITE setGradient RESET resetGradient NOTIFY gradientChanged )
>
> ...
> };
>
> you can write your QML code this way:
>
> MyRectangle
> {
> gradient {
> orientation: "Vertical"
>
> stops: [
> { position: 0.0, color: "MediumAquamarine" },
> { position: 0.5, color: "..." },
> { position: 1.0, color: "DarkSeaGreen" },
> ]
> }
> }
>
> The equivalent code offered by Qt/Quick needs 4 QObjects - for each
> instance of an item. So when having 100 rectangles these are 400 QObjects
> - good for nothing.
>
> Uwe
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
>
Thiago Macieira
2018-05-26 13:17:09 UTC
Permalink
On Saturday, 26 May 2018 09:12:25 -03 Jean-Michaël Celerier wrote:
> If only there was a way to be able to use Qt without all the PIMPLing and
> just have QObjectPrivate be a "normal" QObject member !

You'd save maybe 10% of the allocations. Don't forget that the privates have a
lot of internals that allocate memory too, in the form of vectors, strings,
signal-slot connecion tables, etc.

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Jean-Michaël Celerier
2018-05-26 17:01:59 UTC
Permalink
Well, you mention Nest thermostats : those actually run a Linux with 512 mb
of RAM - more than enough for some QtCore goodness.

> Which is why I don't think Qt has a role to play in these types of
devices.

This I don't understand. There would be so much to win in terms of code
reuse - currently I have a QObject hierarchy for desktop and Qt UI
interoperatibility and a raw C++ object hierarchy for embedded ; I'm just
recreating the same stuff twice. It kills me that the embedded devices I
use are powerful enough to run Python and Javascript interpreters but not
some QObjects.

About the allocations, I don't know: running my app under heaptrack shows
that QObjectPrivate is responsible for a great deal of those - way more
than I would like. Besides, this is not so much a problem of memory than a
problem of cache fragmentation. And in semi-powerful devices like Pi you
can really feel these effects if you are trying to push them to the max.

Ideally, there would be something like QObject but which allows full
constexpr or at least static-initialization; since embedded devices
commonly have static object trees which could be built at compile-time. A
QObjectLiteral of some sorts if you want, like QStringLiteral :p





-------
Jean-Michaël Celerier
http://www.jcelerier.name

On Sat, May 26, 2018 at 3:17 PM, Thiago Macieira <***@intel.com>
wrote:

> On Saturday, 26 May 2018 09:12:25 -03 Jean-Michaël Celerier wrote:
> > If only there was a way to be able to use Qt without all the PIMPLing and
> > just have QObjectPrivate be a "normal" QObject member !
>
> You'd save maybe 10% of the allocations. Don't forget that the privates
> have a
> lot of internals that allocate memory too, in the form of vectors,
> strings,
> signal-slot connecion tables, etc.
>
> --
> Thiago Macieira - thiago.macieira (AT) intel.com
> Software Architect - Intel Open Source Technology Center
>
>
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
Thiago Macieira
2018-05-26 18:04:43 UTC
Permalink
On Saturday, 26 May 2018 14:01:59 -03 Jean-Michaël Celerier wrote:
> Well, you mention Nest thermostats : those actually run a Linux with 512 mb
> of RAM - more than enough for some QtCore goodness.

I said "similar to". Yes, there are some overkill devices for the needs they
have. Usually because whoever made them decided to go for Java or HTML5 UI.

Another reason for 512 MB of RAM is that there are no smaller discrete memory
modules. It's just not worth producing them in scale, so their price is
actually higher than 512 MB, so no one produces them ... vicious cycle.
There's a huge chasm between embedded RAM (order of a few MB) and discrete RAM
(512 MB).

> > Which is why I don't think Qt has a role to play in these types of
> > devices.
>
> This I don't understand. There would be so much to win in terms of code
> reuse - currently I have a QObject hierarchy for desktop and Qt UI
> interoperatibility and a raw C++ object hierarchy for embedded ; I'm just
> recreating the same stuff twice. It kills me that the embedded devices I
> use are powerful enough to run Python and Javascript interpreters but not
> some QObjects.

Qt is not going to run on a device with 16 MB of RAM. Period. Even running a
regular Linux userspace is going to be tricky -- forget systemd at less than
8 MB.

There are JavaScript interpreters for microcontrollers (see Duktape and
Jerryscript). But those are designed to run on tens of *kilobytes* of RAM. You
can't compare them to Qt, as they have special limitations to run that way.
For example, neither implementation supports "eval".

Instead, compare Qt to a full JS interpreter, like V8. You need those 512 MB
for it, otherwise you won't run comfortably. Ditto for Python. But Qt can run
comfortably on 128 MB of RAM, possibly 64. QtCore+QtNetwork plus Websocket or
OPC-UA or CoAP or other IoT protocols can definitely make do at 32 MB.

But like I said, those devices don't exist because 32 MB is just not
economical. Even routers and NAS are coming with 512 MB or 1 GB of RAM, for no
technical reason at all.

> About the allocations, I don't know: running my app under heaptrack shows
> that QObjectPrivate is responsible for a great deal of those - way more
> than I would like. Besides, this is not so much a problem of memory than a
> problem of cache fragmentation. And in semi-powerful devices like Pi you
> can really feel these effects if you are trying to push them to the max.

That's because the Pi is, like you qualified, "semi-powerful". It's not
powerful enough to make those limitations go away by using speculative
execution and pipelining (which is why it wasn't affected by Spectre), but
it's also big enough that people run complex software in it. In other worlds,
it's "the worst of both worlds".

You should choose either a small microcontroller with a dedicated MCU-class OS
that uses static memory allocation, or you should go for an actual powerful
device that will hide those issues by doing other things while it waits for
memory.

> Ideally, there would be something like QObject but which allows full
> constexpr or at least static-initialization; since embedded devices
> commonly have static object trees which could be built at compile-time. A
> QObjectLiteral of some sorts if you want, like QStringLiteral :p

Never going to happen, not in standard Qt anyway. Any such hacks would be
specific to their particular use and hardly reusable. You're getting close to
static memory allocation, which is when you decide at compile time that you're
going to have N such objects and never more. That's how MCU-class OSes
implement TCP/IP for example. They can have at most an configuration-time
chosen number of simultaneous connections. If you try to start one more or if
you receive one more SYN, it will fail.

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Richard Weickelt
2018-05-26 21:20:17 UTC
Permalink
> There are JavaScript interpreters for microcontrollers (see Duktape and
> Jerryscript). But those are designed to run on tens of *kilobytes* of RAM. You
> can't compare them to Qt, as they have special limitations to run that way.
> For example, neither implementation supports "eval".
I wonder if those tiny devices with tens or even hundreds of kilobytes RAM
running Jerryscript would be already sufficient for a "QML light". I am not
talking about QML GUIs, but rather simple sensor/actor applications
consisting of few state machines and using one of the 1001 available
communication stacks.

MCU vendors usually offer and praise their own C SDKs, but my experience so
far is that it can take a very long time to achieve even simple applications
and one has to write either a lot of boilerplate code or use fragile and
obscure tools.

QML has some powerful features that feel like a quantum leap when compared to C:
- property bindings
- easy component composition
- signals, signal handlers
- ...

If we had nice QML modules like Qt Bluetooth and Qt Sensors available for
tiny devices, I believe that application development would become very
simple and convenient. I am making a few assumptions here:

- the whole application structure would be static, no dynamic loading
of components
- bindings are resolved at build-time.
- the application would be compiled to bytecode on the host before
being flashed onto the target
- the back-end of those modules would most likely not be Qt
- it would be possible to deduce, which features the QML
application actually uses so that unused functionality can be
dropped at build-time.

I would be interested in other opinions. Maybe I am on a completely wrong
track here.

Richard
Thiago Macieira
2018-05-26 22:25:01 UTC
Permalink
On Saturday, 26 May 2018 18:20:17 -03 Richard Weickelt wrote:
> > There are JavaScript interpreters for microcontrollers (see Duktape and
> > Jerryscript). But those are designed to run on tens of *kilobytes* of RAM.
> > You can't compare them to Qt, as they have special limitations to run
> > that way. For example, neither implementation supports "eval".
>
> I wonder if those tiny devices with tens or even hundreds of kilobytes RAM
> running Jerryscript would be already sufficient for a "QML light". I am not
> talking about QML GUIs, but rather simple sensor/actor applications
> consisting of few state machines and using one of the 1001 available
> communication stacks.

It would be interesting to explore. QML is nothing but a property-binding and
object-instantiating syntax on top of JS, so it could be done.

> MCU vendors usually offer and praise their own C SDKs, but my experience so
> far is that it can take a very long time to achieve even simple applications
> and one has to write either a lot of boilerplate code or use fragile and
> obscure tools.

Hence the use of JS.

See https://elinux.org/images/f/ff/JavaScript_Meets_Zephyr.pdf

Disclaimer: Sakari is a colleague of mine. And some of the folks at TQtC may
remember him from Nokia times, as he worked on Maemo/MeeGo.

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Uwe Rathmann
2018-05-26 12:52:59 UTC
Permalink
On Sat, 26 May 2018 12:05:38 +0000, Simon Hausmann wrote:

> P.S.: Are you sure the stops: [ ... ] assignment works?

You are right: I forgot to mention this extra piece of code:

QMetaType::registerConverter< QJSValue, QskGradientStop >(

[] (const QJSValue& value) -> QskGradientStop
{
return
{
value.property( QLatin1String("position") ).toNumber(),
value.property( QLatin1String("color") ).toVariant
().value< QColor >()
};
}
);

It can be found in https://github.com/uwerat/qskinny/blob/master/src/
common/QskModule.cpp.

Most of the tricks for exposing stuff to QML have been written by Andrew
( Knight ) who is way more familiar with the QML world than I am.

In the beginning we were not sure if we will be able to come up with a
framework, that allows us to get rid of QML in general. That's why we
played with ways how to expose our APIs to QML without creating the same
overhead you find in the existing classes.

Today the QML API is not in the focus of the application driving the
development of QSkinny. But from the initial proof of concept it is
pretty clear that I can expose - let's say 80-90 % of the API - to QML
easily.

But a Qt/Quick application is always a combination of QML and C++ and I
don't see why it is necessary trying to do as much as possible in the QML
part.

Uwe
Jedrzej Nowacki
2018-05-28 12:04:01 UTC
Permalink
On Saturday, May 26, 2018 2:05:38 PM CEST Simon Hausmann wrote:
> Jędrzej had a beautiful proof of concept at some point for QObject to
> combine the object and d-pointer allocation into one.

Old times :-)
For completeness: https://codereview.qt-project.org/#/q/status:deferred
+project:qt/qtbase+branch:dev+topic:qobject_operator_new,n,z
Sérgio Martins
2018-05-25 13:54:41 UTC
Permalink
On 2018-05-25 12:12, Uwe Rathmann wrote:

> So for the next generation of our product we started to implement our
> own framework on top of the C++ part of Qt/Quick (
> https://github.com/uwerat/qskinny ). Our user interface today consists
> about ~200K lines of code ( pure C++ ) and so far I can say that the
> typical problems of having a bad startup performance or the heavy
> memory
> footprint simple don't exist.
>
> Unfortunately we still have to maintain our previous product written in
> QML for many years. Maybe we can migrate it step by step to our new
> framework.

You might also have problems maintaining qskinny since it's using
private API.

Which brings the question, should the needed API be made public ? Are
there any parts of qskinny and/or patches
that should be integrated to make it easier for such frameworks ?

I think both QML-QtQuick and C++-QtQuick have their merits and we could
improve the situation for the later.



Regards,
--
Sérgio Martins | ***@kdab.com | Senior Software Engineer
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel: Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - The Qt, C++ and OpenGL Experts
Loading...