Details
-
Bug
-
Resolution: Out of scope
-
Not Evaluated
-
None
-
4.8.0
-
None
-
QWS on Embedded Linux, ARM9 200Mhz
Description
We came across an issue while working on our application that has a large amount of widgets (4500+) and a very slow CPU - arm9 200 Mhz.
The issue was an incredibly large delays when displaying dialogs. According to our benchmarks, the dialog was spending around 450ms inside the show() method.
After investigating this issue, the following things were discovered:
- allWidgets is a static QSet<QWidget*> , but, to perform iterations on that set, it's first converted (using shallow copy) to a QList, and it's done on every call to allWidgets()
- several functions (topLevelWidgets(), enterModal(), etc) use the result of that function inefficiently, causing allWidgets() to be called several times and copied over again and again
- topLevelWidgets() is a function that is called every time when dialogs are displayed. It's implementation is unoptimized, it searches the WHOLE list of widgets EVERY time just to find the list of top level widgets.
- when a QDialog appears a WindowBlocked event is sent to ALL non-window widgets in the system. (even the hidden ones).
To handle the 4th issue, we've applied the same conditions used in handling WindowActivated/Deactivated event, i.e. added a "don't forward to hidden widgets" condition.
You can see our modification in patch named improve_windowBlocked.patch attached. Using this change, we've improved performance of dialog opening from 450ms to 140ms.
To handle the first 3 issues, two approaches can be used.
a) Improve topLevelWidgets() function so that it will work directly with allWidgets set and will not require list conversion.
You can see our modification in patch named improve_topLevel1.patch attached. Using this change, we've improved performance of dialog opening from 140ms to 90ms.
b) An even better solution would be to maintain a separate QSet of widgets just for the top level ones. This would save us from the iteration and comparison.
You can see our modification in patch named improve_topLevel2.patch attached. Using this change, we've improved performance of dialog opening from 90ms to 45ms.
We'd recommend applying both improve_windowBlocked.patch and the improve_topLevel2.patch due to better performance
If you consider improve_topLevel2.patch too intrusive, even the improve_topLevel1.patch would improve the situation.