https://bugs.kde.org/show_bug.cgi?id=442465
Bug ID: 442465 Summary: Creating QProxyStyle creates many Breeze::Style, installing QApplication event handlers and slowing down app Product: Breeze Version: git-master Platform: Archlinux Packages OS: Linux Status: REPORTED Severity: normal Priority: NOR Component: QStyle Assignee: plasma-b...@kde.org Reporter: nyanpas...@tuta.io CC: noaha...@gmail.com Target Milestone: --- SUMMARY Creating a QProxyStyle and setting it to a widget creates a Breeze::Style, installing event filters on QApplication and slowing down application events, more so as you create hundreds or thousands of QProxyStyle. I'm not sure if this is a bug or by design. STEPS TO REPRODUCE 1. Clone and run https://github.com/nyanpasu64/qproxystyle-lag. 2. Click "Open file dialog" and notice it's quick to open and close. 3. Click "Generate lag" and wait for the app to finish creating 2048 QSlider with QProxyStyle. OBSERVED RESULT At some point after connecting QProxyStyle to QSlider (I think when QSlider layouts), QSlider calls QProxyStylePrivate::ensureBaseStyle()[1], which calls QStyleFactory::create(QString const&), and qLoadPlugin<QStyle, QStylePlugin>. As a result, each QProxyStyle constructs a separate instance of Breeze::Style. [1]: https://invent.kde.org/qt/qt/qtbase/-/blob/kde/5.15/src/widgets/styles/qproxystyle.cpp#L78 Each Breeze::Style constructed installs two app-wide event filters (QApplication::installEventFilter()), one from Breeze::WindowManager::WindowManager(), and one from Breeze::Mnemonics::setMode(). After "Generate lag" completes, "Open file dialog" takes a long time to open or close (spending time in QCoreApplicationPrivate::sendThroughApplicationEventFilters()), and the app remains unresponsive for a second after the dialog closes (spending time in Breeze::ToolsAreaManager::configUpdated()). If you click "Delete widgets", all QWidget are deleted, and the dialog opens and closes quickly (no more waiting in QCoreApplicationPrivate::sendThroughApplicationEventFilters()), but the main window remains unresponsive after closing the dialog (waiting in Breeze::ToolsAreaManager::configUpdated()). If you click "Delete styles", the opposite happens. EXPECTED RESULT Commenting out `custom->setStyle(style);` (creating 2048 QSlider and 2048 QProxyStyle, but leaving the QProxyStyle unused) makes "Generate lag" complete instantly (since QProxyStylePrivate::ensureBaseStyle() is never called), and fixes the "Open file dialog" lag entirely. SOFTWARE/OS VERSIONS Operating System: Arch Linux KDE Plasma Version: 5.22.5 (both Breeze 5.22.5 and master) KDE Frameworks Version: 5.86.0 Qt Version: 5.15.2 Kernel Version: 5.14.2-zen1-2-zen (64-bit) Graphics Platform: X11 Processors: 12 × AMD Ryzen 5 5600X 6-Core Processor Memory: 15.6 GiB of RAM Graphics Processor: NVIDIA GeForce GT 730/PCIe/SSE2 ADDITIONAL INFORMATION I'm not sure if this is a Qt bug (each QProxyStyle constructing an independent QStyle instead of reusing QStyle by name), a Breeze bug (each Breeze::Style slowing down the application by a tiny bit), or an application bug (it's the responsibility of the app to not create thousands of QProxyStyle, even though thousands of QWidget doesn't cause an analogous slowdown). I'm not sure how to address this. Maybe the Breeze::Style instances could coordinate to not install O(n) event filters and spend O(n) time responding to config changes? And if Breeze::Style is stateless, maybe the instances could share their internals? I don't think Breeze can return the same Breeze::Style heap allocation for multiple QProxyStyle, because QStyleFactory::create() is supposed to return a unique pointer. You'd have to change Qt, not Breeze, to get QProxyStyle to reuse underlying styles. And this wouldn't fix applications which don't use QProxyStyle, but call QStyleFactory::create() themselves to generate hundreds or thousands of QStyle objects. -- You are receiving this mail because: You are watching all bug changes.