Author Topic: wxUpdateUIEvent performance issues  (Read 12646 times)

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
wxUpdateUIEvent performance issues
« on: December 11, 2009, 05:17:11 pm »
This could be a storm in a teacup, but I've lately been scratching my head about the sluggish editor performance on Linux. One potential culprit could be the UI update handling. This issue has come up before: http://forums.codeblocks.org/index.php/topic,5341.0.html

looking in main.cpp I see lots of EVT_UPDATE_UI macros:

Code
    EVT_UPDATE_UI(idFileOpenRecentFileClearHistory, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileOpenRecentProjectClearHistory, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileSave, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveAs, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveAllFiles, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileOpenDefWorkspace, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveWorkspace, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveWorkspaceAs, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileCloseWorkspace, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileClose, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileCloseAll, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFilePrintSetup, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFilePrint, MainFrame::OnFileMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveProject, MainFrame::OnProjectMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveProjectAs, MainFrame::OnProjectMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveProjectAllProjects, MainFrame::OnProjectMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveProjectTemplate, MainFrame::OnProjectMenuUpdateUI)
    EVT_UPDATE_UI(idFileSaveAll, MainFrame::OnProjectMenuUpdateUI)
    EVT_UPDATE_UI(idFileCloseProject, MainFrame::OnProjectMenuUpdateUI)

I also see a bunch of Update UI handling in plugins

In the wx docs (http://docs.wxwidgets.org/stable/wx_wxupdateuievent.html#wxupdateuievent) we see the following suggestions:

Quote
If you find that the overhead of UI update processing is affecting your application, you can do one or both of the following:

   1. Call wxUpdateUIEvent::SetMode with a value of wxUPDATE_UI_PROCESS_SPECIFIED, and set the extra style wxWS_EX_PROCESS_UPDATE_EVENTS for every window that should receive update events. No other windows will receive update events.
   2. Call wxUpdateUIEvent::SetUpdateInterval with a millisecond value to set the delay between updates. You may need to call wxWindow::UpdateWindowUI at critical points, for example when a dialog is about to be shown, in case the user sees a slight delay before windows are updated.

Based on the post I linked to at the start, we appear to be following suggestion #2 (line 411 in app.cpp)

Code
    wxUpdateUIEvent::SetUpdateInterval(100);

but is this enough? Could waking up every 100ms to update the menus explain the poor editing and idle performance of C::B on linux?

see attached, which show the result of logging the # of Editor Menu updates while C::B sits idle with an editor open! They come in at roughly 1 per 100ms, I haven't yet tried to time how much time is spent in these events. However, helpfully, I only see the update spam after an editor has been opened or if I move the mouse around a lot. So I played around with "top" on my lightweight eee pc (note that this is after I switch of the logging I show in the screenshot below -- it's much worse with it on). With no mouse action and all editors closed, C::B generates sits quietly. As soon as I open an editor, C::B jumps to the top of the top queue and doesn't leave it. Similar behavior on windows, but the performance penalty seem to be much more minor...

As far as a fix goes, I think we need to dig in a little and find out why so many update events occur at idle when an editor is open but not when closed...

[attachment deleted by admin]
« Last Edit: December 11, 2009, 05:20:13 pm by dmoore »

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: wxUpdateUIEvent performance issues
« Reply #1 on: December 11, 2009, 07:58:17 pm »
Hmm... this brings up another thing. I've noticed that Code::Blocks really sucks dick if you run it via XDMCP (even on a 1Gbps network with a single Netgear router in between and roughly 4 meters of total cable length).
It takes upwards of half a second (usually more) before Code::Blocks registers a mouse click or opens a menu. I've always wondered why XDMCP performance is so abysmal, especially since other programs run as if they were started locally.

Now, gears in my head start moving... what if this infrequent event polling in combination with the network latency (probably 1ms or less, but still...) is what screws it all up?
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: wxUpdateUIEvent performance issues
« Reply #2 on: December 11, 2009, 11:12:21 pm »
Hmm... this brings up another thing. I've noticed that Code::Blocks really sucks dick if you run it via XDMCP (even on a 1Gbps network with a single Netgear router in between and roughly 4 meters of total cable length).
It takes upwards of half a second (usually more) before Code::Blocks registers a mouse click or opens a menu. I've always wondered why XDMCP performance is so abysmal, especially since other programs run as if they were started locally.

Now, gears in my head start moving... what if this infrequent event polling in combination with the network latency (probably 1ms or less, but still...) is what screws it all up?

does it just suck only while you have a scintilla window open or for everything? e.g. try opening something in the hex editor (no other windows open) - that doesn't seem to create the idle event spam...

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: wxUpdateUIEvent performance issues
« Reply #3 on: December 12, 2009, 02:03:27 pm »
For now I think I give up in disgust. This is a wxWidgets/wxScintilla problem. Something inside of wxScintilla is generating a constant stream of idle events, which in turn spins up the update ui events. That doesn't mean wxScintilla is explicitly sending idle events of course, just that it's doing something to make the wx event loop think its time to send another idle event. I guess it could be something as stupid as the cursor flashing? I've tried overriding wxApp::FilterEvent to see if I could figure out what events were being fired, but didn't see anything obvious besides the stream of update ui and idle events.

As far as performance goes, I guess on windows this isn't an issue at all, and only seems to effect light weight linux systems. Assuming it is worth fixing, I don't think it's enough to block the update ui events, it would be much better to prevent whatever wxScintilla's high frequency activity from generating (so many) on idle events. It's still amusing that we check/uncheck everything in the menubar every 100ms and do more than 100 times just running the mouse from one end of the screen to the other.
« Last Edit: December 12, 2009, 02:27:10 pm by dmoore »

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: wxUpdateUIEvent performance issues
« Reply #4 on: December 12, 2009, 02:14:23 pm »
I did one more check.... it's the f***ing cursor.

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: wxUpdateUIEvent performance issues
« Reply #5 on: December 12, 2009, 04:54:28 pm »
Hmm... this brings up another thing. I've noticed that Code::Blocks really sucks dick if you run it via XDMCP (even on a 1Gbps network with a single Netgear router in between and roughly 4 meters of total cable length).
It takes upwards of half a second (usually more) before Code::Blocks registers a mouse click or opens a menu. I've always wondered why XDMCP performance is so abysmal, especially since other programs run as if they were started locally.

Now, gears in my head start moving... what if this infrequent event polling in combination with the network latency (probably 1ms or less, but still...) is what screws it all up?

just moving the mouse around a bit can generate hundreds of update ui events. (i.e. the 100ms UpdateInterval doesn't really stop the events, perhaps just delays them). that might do it?

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: wxUpdateUIEvent performance issues
« Reply #6 on: December 23, 2009, 10:52:30 am »
One thing to reduce the amount of calls to the event-functions is to bind only one ID to the appropriate OnxxxMenuUpdateUI-function.
It should be an ID that is used by the menu and the toolbar.
I tested with idFileSave, idFileSaveProject (only needed for the Project menu, not a toolbar), idEditUndo, idSearchFind and idViewToolMain (just for the View-menu).
All other bindings are redundant, because they do the exactly same thing and do nothing but create unnecessary overhead.
The same can be done for the compiler- and debugger-plugin (idMenuCompile and XRCID("idDebuggerMenuDebug")).
All other bindings can be commented out, without changing the behaviour (of course only the EVT_UPDATE_UI-macros should be commented out).
Setting the update-interval to 500 ms reduces the overhead some more, without slowing down update too much, at least for me.

Please test (if you find the time) and post your experience with it.