Discussion:
Optimizing performance with hundreds of widgets
(too old to reply)
Gibbs, Matt
2017-02-15 17:28:22 UTC
Permalink
Hi All,

I’m working on a Qt-based project to display rapidly updating information from a control system. I want to display hundreds of signals, each updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in a grid layout, and fire a timer every 100 ms which calls setText on each label. This ends up being surprisingly CPU-intensive: on reasonably modern hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me much overhead to do anything else.

Are there any best practices to reduce CPU usage in this case?

Cheers,
—Matt

Matt Gibbs
SLAC Accelerator Operations Group
***@slac.stanford.edu
Elvis Stansvik
2017-02-21 12:27:04 UTC
Permalink
Post by Gibbs, Matt
Hi All,
I’m working on a Qt-based project to display rapidly updating information from a control system. I want to display hundreds of signals, each updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in a grid layout, and fire a timer every 100 ms which calls setText on each label. This ends up being surprisingly CPU-intensive: on reasonably modern hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me much overhead to do anything else.
Are there any best practices to reduce CPU usage in this case?
Hm, I don't really have a good answer when it comes to optimizing it
the way you've stated it, but lets get a little philosophical instead:
What human operator of your GUI is going to be able to process all
this visual information? I would have a hard time monitoring even 5
labels of text updating at that rate.

My recommendation would be:

1. Consider if your really have to show all these sensors, or if the
information they're conveying can be aggregated in some way.
2. If you really need to visualize them all at once, consider a
simpler presentation than the numerical, such as a bar (should be
cheaper to redraw than a changing text).

Regarding 1, if the sensors can be grouped in some logical way, you
can present a collection of sensor groups instead. Regarding 2, if the
user wants to look closer at a single sensor, or maybe a (reasonably
sized) group of sensors, you could build some UI for that.

It would help to know a little more about the user story, is this for
monitoring a system for failures? If so, I think the rule of thumb is
that if nothing is out of the ordinary, the system should not look
visually "busy" (no big movements or bright colors, just subtle
gray/static text). That allows you to use visual movement and bright
colors for error conditions / anomalies. But yea, it would help to
know more about what the GUI is for :)

Hope that helps a little, even if it wasn't what you asked for.

Elvis
Post by Gibbs, Matt
Cheers,
—Matt
Matt Gibbs
SLAC Accelerator Operations Group
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Elvis Stansvik
2017-02-21 12:33:33 UTC
Permalink
Post by Elvis Stansvik
Post by Gibbs, Matt
Hi All,
I’m working on a Qt-based project to display rapidly updating information from a control system. I want to display hundreds of signals, each updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in a grid layout, and fire a timer every 100 ms which calls setText on each label. This ends up being surprisingly CPU-intensive: on reasonably modern hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me much overhead to do anything else.
Are there any best practices to reduce CPU usage in this case?
Hm, I don't really have a good answer when it comes to optimizing it
What human operator of your GUI is going to be able to process all
this visual information? I would have a hard time monitoring even 5
labels of text updating at that rate.
1. Consider if your really have to show all these sensors, or if the
information they're conveying can be aggregated in some way.
2. If you really need to visualize them all at once, consider a
simpler presentation than the numerical, such as a bar (should be
cheaper to redraw than a changing text).
Regarding 1, if the sensors can be grouped in some logical way, you
can present a collection of sensor groups instead. Regarding 2, if the
user wants to look closer at a single sensor, or maybe a (reasonably
sized) group of sensors, you could build some UI for that.
It would help to know a little more about the user story, is this for
monitoring a system for failures? If so, I think the rule of thumb is
that if nothing is out of the ordinary, the system should not look
visually "busy" (no big movements or bright colors, just subtle
gray/static text). That allows you to use visual movement and bright
colors for error conditions / anomalies. But yea, it would help to
know more about what the GUI is for :)
Another powerful UI design principle is (as I hinted at) "drill down"
UIs -- find some way of aggregating the information, and let the user
drill down deeper if he/she wants to know/see more.

The fidelity you're aiming for (500 numbers, presented numerically @
10 Hz) is too much bandwidth, not only for your MacBook, for also for
any human.

Elvis
Post by Elvis Stansvik
Hope that helps a little, even if it wasn't what you asked for.
Elvis
Post by Gibbs, Matt
Cheers,
—Matt
Matt Gibbs
SLAC Accelerator Operations Group
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Elvis Stansvik
2017-02-21 19:06:20 UTC
Permalink
Hi Elvis, thanks for your thoughtful reply.
Loading Image... (Right now our accelerator is in a maintenance period, hence all the yellow, purple, and red alarm boxes you see. In normal running, most everything has no alarm.)
These displays are almost certainly overwhelming to a brand-new user, but the users for these screens are experts who know the system very well, know what to look for, and appreciate the massive data density that they provide. We structure our displays hierarchically: top-level overview screens that represent entire systems as a single indicator, mid-level screens which display summary signals for subsystems, displays that show the most useful signals for devices in a subsystem (like this example), and finally, device detail screens that show all signals for a single device. You drill down through the displays from the top-level down to a single device, so we do something similar to what you are suggest.
That said, many of the text labels (and sliders) you see on this example display are connected at signals that refresh at 10 Hz, and there are a bunch - I count something like 180 widgets on this display that could potentially be updating if their signals were all changing at the same time. This isn’t too far removed from my label test, so I think advice for how to optimize this case is not irrelevant.
Thanks for sharing! Looks quite interesting. I didn't mean to suggest
your ask for advice was irrelevant (I'm actually curious myself).
Sorry if it came across like that :)

Sounds like you have a good overall design in your current system, and
yes, the human mind is good with patterns, so monitoring hundreds of
signals is perhaps not unreasonable after all, especially with a lot
of experience. And even if you can't possibly parse every time/value
data point, there's value in being to able to just look at some sensor
you're interested in straight away, without having to drill down.

I think André's advise sounds pretty good, so maybe try cooking up a
version of your 500 item test case that instead uses a table view
hooked up to a custom model with a custom item delegate that paints
the items.

Also, are the sensor values all read simultaneously (like your test
case suggest), or do they arrive asynchronously and somewhat
independently? If the latter, maybe try making the test case more
realistic.

Elvis
Cheers,
—Matt
Post by Elvis Stansvik
Post by Elvis Stansvik
Post by Gibbs, Matt
Hi All,
I’m working on a Qt-based project to display rapidly updating information from a control system. I want to display hundreds of signals, each updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in a grid layout, and fire a timer every 100 ms which calls setText on each label. This ends up being surprisingly CPU-intensive: on reasonably modern hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me much overhead to do anything else.
Are there any best practices to reduce CPU usage in this case?
Hm, I don't really have a good answer when it comes to optimizing it
What human operator of your GUI is going to be able to process all
this visual information? I would have a hard time monitoring even 5
labels of text updating at that rate.
1. Consider if your really have to show all these sensors, or if the
information they're conveying can be aggregated in some way.
2. If you really need to visualize them all at once, consider a
simpler presentation than the numerical, such as a bar (should be
cheaper to redraw than a changing text).
Regarding 1, if the sensors can be grouped in some logical way, you
can present a collection of sensor groups instead. Regarding 2, if the
user wants to look closer at a single sensor, or maybe a (reasonably
sized) group of sensors, you could build some UI for that.
It would help to know a little more about the user story, is this for
monitoring a system for failures? If so, I think the rule of thumb is
that if nothing is out of the ordinary, the system should not look
visually "busy" (no big movements or bright colors, just subtle
gray/static text). That allows you to use visual movement and bright
colors for error conditions / anomalies. But yea, it would help to
know more about what the GUI is for :)
Another powerful UI design principle is (as I hinted at) "drill down"
UIs -- find some way of aggregating the information, and let the user
drill down deeper if he/she wants to know/see more.
10 Hz) is too much bandwidth, not only for your MacBook, for also for
any human.
Elvis
Post by Elvis Stansvik
Hope that helps a little, even if it wasn't what you asked for.
Elvis
Post by Gibbs, Matt
Cheers,
—Matt
Matt Gibbs
SLAC Accelerator Operations Group
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
Elyzabeth von Reuenthal
2017-02-21 13:15:55 UTC
Permalink
Post by Gibbs, Matt
Are there any best practices to reduce CPU usage in this case?
In case it is necessary to display all of this data at once, is it possible to
offload it to the GPU by displaying it using OpenGL instead of regular widgets?
You could either use QML and QQuickWidget, or if using C++, there is
QOpenGLPaintDevice which enables the use of QPainter (and so,
QPainter::drawText).

Hope this is of use.
Viktor Engelmann
2017-02-21 13:39:39 UTC
Permalink
Post by Gibbs, Matt
Hi All,
I’m working on a Qt-based project to display rapidly updating information from a control system. I want to display hundreds of signals, each updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in a grid layout, and fire a timer every 100 ms which calls setText on each label. This ends up being surprisingly CPU-intensive: on reasonably modern hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me much overhead to do anything else.
Are there any best practices to reduce CPU usage in this case?
Cheers,
—Matt
Matt Gibbs
SLAC Accelerator Operations Group
_______________________________________________
Interest mailing list
http://lists.qt-project.org/mailman/listinfo/interest
you might want to do

setUpdatesEnabled(false);
// do your updates
setUpdatesEnabled(true);
--
Viktor Engelmann
Software Engineer

The Qt Company GmbH
Rudower Chaussee 13
D-12489 Berlin

***@qt.io
+49 151 26784521

http://qt.io
Geschäftsführer: Mika Pälsi, Juha Varelius, Mika Harjuaho
Sitz der Gesellschaft: Berlin
Registergericht: Amtsgericht Charlottenburg, HRB 144331 B
BAILLY Yves
2017-02-21 13:41:45 UTC
Permalink
I'd consider using QGraphicsScene/QGraphicsView maybe with a QOpenGLWidget as viewport. See the example "40000 ships" http://doc.qt.io/qt-5/qtwidgets-graphicsview-chip-example.html

-----Original Message-----
From: Interest [mailto:interest-bounces+yves.bailly=***@qt-project.org] On Behalf Of Gibbs, Matt
Sent: 15 February 2017 18:28
To: ***@qt-project.org
Subject: [Interest] Optimizing performance with hundreds of widgets

Hi All,

I’m working on a Qt-based project to display rapidly updating information from a control system. I want to display hundreds of signals, each updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in a grid layout, and fire a timer every 100 ms which calls setText on each label. This ends up being surprisingly CPU-intensive: on reasonably modern hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me much overhead to do anything else.

Are there any best practices to reduce CPU usage in this case?

Cheers,
—Matt

Matt Gibbs
SLAC Accelerator Operations Group
***@slac.stanford.edu
_______________________________________________
Interest mailing list
***@qt-project.org
http://lists.qt-project.org/mailman/listinfo/interest
Guenter Schwann
2017-02-21 14:36:12 UTC
Permalink
Post by Gibbs, Matt
Hi All,
I’m working on a Qt-based project to display rapidly updating information
from a control system. I want to display hundreds of signals, each
updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in
a grid layout, and fire a timer every 100 ms which calls setText on each
label. This ends up being surprisingly CPU-intensive: on reasonably modern
hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me
much overhead to do anything else.
I get about 25% CPU usage on my 2.5GHz Linux Notebook.
And when I use a single custom widget to draw all texts in a single
paintEvent, CPU usage drops to about 15%.

https://gitlab.com/gschwann/WidgetsPerformance
--
Günter Schwann | Freelancing Software Engineer | Qt Expert
Partner Consultant of Viking Software
***@vikingsoft.eu
Gibbs, Matt
2017-02-21 21:35:41 UTC
Permalink
Hi Guenter, thanks for the reply, and the sample code.

I’ll check it out - I bet having a very simple widget that only calls painter.drawText like yours will help. I can’t go all the way to a single widget, unfortunately, but avoiding all the ‘fancy’ parts of QLabel is a good idea.

—Matt
Post by Guenter Schwann
Post by Gibbs, Matt
Hi All,
I’m working on a Qt-based project to display rapidly updating information
from a control system. I want to display hundreds of signals, each
updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in
a grid layout, and fire a timer every 100 ms which calls setText on each
label. This ends up being surprisingly CPU-intensive: on reasonably modern
hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me
much overhead to do anything else.
I get about 25% CPU usage on my 2.5GHz Linux Notebook.
And when I use a single custom widget to draw all texts in a single
paintEvent, CPU usage drops to about 15%.
https://gitlab.com/gschwann/WidgetsPerformance
--
Günter Schwann | Freelancing Software Engineer | Qt Expert
Partner Consultant of Viking Software
André Pönitz
2017-02-21 17:23:12 UTC
Permalink
Post by Gibbs, Matt
Hi All,
I’m working on a Qt-based project to display rapidly updating
information from a control system. I want to display hundreds of
signals, each updating at about 10 Hz. As a performance test, I’ve
thrown 500 Labels in a grid layout, and fire a timer every 100 ms
which calls setText on each label. This ends up being surprisingly
CPU-intensive: on reasonably modern hardware (2012 MacBook Pro), I use
70% of one CPU. This doesn’t leave me much overhead to do anything
else.
Are there any best practices to reduce CPU usage in this case?
If the labels simply display some text I'd finger-paint that in
the paint event. Or, if it needs to be scrollable/have some
table-like interaction then a QTableView with a simple
QAbstractTableModel implementation and an item delegate for
the actual painting.

Andre'
Adam Light
2017-02-26 00:48:58 UTC
Permalink
Post by Gibbs, Matt
Hi All,
I’m working on a Qt-based project to display rapidly updating information
from a control system. I want to display hundreds of signals, each
updating at about 10 Hz. As a performance test, I’ve thrown 500 Labels in
a grid layout, and fire a timer every 100 ms which calls setText on each
label. This ends up being surprisingly CPU-intensive: on reasonably modern
hardware (2012 MacBook Pro), I use 70% of one CPU. This doesn’t leave me
much overhead to do anything else.
Are there any best practices to reduce CPU usage in this case?
Though I haven't checked to see whether or not this actually affects
performance, I would suggest callint setTextFormat(Qt::PlainText) to avoid
the need to inspect the string to determine whether it's rich text.

Also, based on the image you shared, I'd guess that most of the values that
are changing might be better displayed within QLineEdit widgets. You might
find that QLineEdit has better performance because I suspect there is less
to do in terms of laying out the text and such.

Adam
Continue reading on narkive:
Loading...