Skip to content

"Load ROM..." dialog uses too much CPU #188

Open
@Screwtapello

Description

@Screwtapello

Steps to reproduce

  1. Start bsnes
  2. disable the animated snow, it's enabled
  3. From the System menu, choose Load Game...

Expected results

Near-zero CPU usage

Actual results

bsnes consumes a CPU core

Notes

This was reported on the Discord under Windows, but reproduced on Linux/GTK+3.

perf top report

perf top isn't great at digging out symbol names for some reason.

62.54%     0.00%  bsnes    [unknown]
27.64%    25.28%  bsnes    libpango-1.0.so.0.4800.2
17.44%     7.14%  bsnes    libc-2.31.so
17.26%    15.31%  bsnes    libglib-2.0.so.0.6600.8
16.22%    15.59%  bsnes    libharfbuzz.so.0.20704.0
12.91%    12.86%  bsnes    [kernel.kallsyms]
 7.50%     6.82%  bsnes    libgobject-2.0.so.0.6600.8
 6.64%     5.52%  bsnes    bsnes
 4.55%     1.69%  bsnes    libpthread-2.31.so
 1.98%     1.76%  bsnes    libpangocairo-1.0.so.0.4800.2
 1.69%     1.56%  bsnes    libpangoft2-1.0.so.0.4800.2
 1.52%     1.38%  bsnes    libgdk-3.so.0.2404.20
 1.19%     1.06%  bsnes    libxcb.so.1.1.0
 1.06%     0.92%  bsnes    libcairo.so.2.11600.0
 0.98%     0.94%  bsnes    libX11.so.6.4.0
 0.75%     0.74%  bsnes    libfontconfig.so.1.12.0
 0.49%     0.44%  bsnes    libgtk-3.so.0.2404.20
 0.44%     0.40%  bsnes    libdbus-1.so.3.19.13
 0.36%     0.31%  bsnes    libfribidi.so.0.4.0
 0.13%     0.13%  bsnes    libstdc++.so.6.0.28
 0.09%     0.09%  bsnes    [vdso]
 0.07%     0.05%  bsnes    libatspi.so.0.0.1
 0.00%     0.00%  bsnes    [scsi_mod]
gdb traceback

Captured at some arbitrary point in the proceedings

#0  0x00007f2baaa02780 in g_slice_free_chain_with_offset () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#1  0x00007f2baac8c72c in  () at /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0
#2  0x00007f2baac8e6a4 in  () at /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0
#3  0x00007f2baaada11e in g_object_unref () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#4  0x000055898d2ef4d8 in hiro::pFont::size(_PangoFontDescription*, nall::string const&) (font=font@entry=0x55899439f580, text=...)
    at ../hiro/core/../gtk/font.cpp:19
#5  0x000055898d2ffd5e in hiro::pFont::size(hiro::Font const&, nall::string const&) (font=..., text=...)
    at ../hiro/core/../gtk/font.cpp:7
#6  0x000055898d3007e3 in hiro::Font::size(nall::string const&) const (this=this@entry=0x7ffcc942b6b0, text=...)
    at ../hiro/core/font.cpp:71
#7  0x000055898d308932 in hiro::pWindow::_menuTextHeight() const (this=this@entry=0x558991ee6ce0) at ../hiro/core/../gtk/window.cpp:463
#8  0x000055898d3089d1 in hiro::pWindow::_menuHeight() const (this=this@entry=0x558991ee6ce0) at ../hiro/core/../gtk/window.cpp:453
#9  0x000055898d30976a in hiro::pWindow::_synchronizeGeometry() (this=0x558991ee6ce0) at ../hiro/core/../gtk/window.cpp:574
#10 0x000055898d30f266 in hiro::pApplication::processEvents() () at ../hiro/core/../gtk/application.cpp:49
#11 0x000055898d30f2c9 in hiro::Application::processEvents() () at ../hiro/core/application.cpp:46
#12 0x000055898d310035 in hiro::pWindow::setModal(bool) (this=0x5589945bb450, modal=modal@entry=true)
    at ../hiro/core/../gtk/window.cpp:399
#13 0x000055898d3100a5 in hiro::mWindow::setModal(bool) (this=0x5589942e1f30, modal=<optimized out>) at ../hiro/core/window.hpp:3
#14 0x000055898d3558d5 in hiro::Window::setModal(bool) (this=0x7ffcc942c018, modal=<optimized out>) at ../hiro/core/shared.hpp:946
#15 0x000055898d338893 in hiro::BrowserDialogWindow::run() (this=this@entry=0x7ffcc942bff0) at ../hiro/extension/browser-dialog.cpp:362
#16 0x000055898d3390ce in hiro::BrowserDialog::_run() (this=this@entry=0x7ffcc942c460) at ../hiro/extension/browser-dialog.cpp:524
#17 0x000055898d33994a in hiro::BrowserDialog::openObject() (this=this@entry=0x7ffcc942c460)
    at ../hiro/extension/browser-dialog.cpp:449
#18 0x000055898d4dd0ec in Program::openGame(hiro::BrowserDialog&) (this=this@entry=0x558990438260 <program>, dialog=...)

It looks like when bsnes opens the file dialog as a modal dialog, it doesn't just use the GTK "make modal dialog" function (whatever that is), it tries to make its own event loop and pump events (see pWindow::setModal in hiro/gtk/window.cpp). However, it doesn't have any way to wait for an event, so it busy-loops calling bsnes' Program::main() method and proactively updating the size of every window. Updating window sizes means a whole bunch of text measurement, which is why pango and harfbuzz show up.

I don't know why hiro doesn't use GTK's (or Windows') native modal feature; if it's a quirk of GTK2 or Qt4 perhaps we can be rid of it, but if it's a quirk of Windows or macOS or GTK3 or Qt5, I think we're stuck with it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions