Description
Steps to reproduce
- Start bsnes
- disable the animated snow, it's enabled
- 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.