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.

Reply via email to