views:

276

answers:

3

I am using wxWidgets and Visual C++ to create functionality similar to using Unix "tail -f" with rich formatting (colors, fonts, images) in a GUI. I am targeting both wxMSW and wxMAC.

The obvious answer is to use wxTextCtrl with wxTE_RICH, using calls to wxTextCtrl::SetDefaultStyle() and wxTextCtrl::WriteText().

However, on my 3ghz workstation, compiled in release mode, I am unable to keep tailing a log that grows on average of 1 ms per line, eventually falling behind. For each line, I am incurring:

  1. Two calls to SetDefaultStyle()
  2. Two calls two WriteText()
  3. A call to Freeze() and Thaw() the widget

When running this, my CPU goes to 100% on one core using wxMSW after filling up roughly 20,000 lines. The program is visibly slower once it reaches a certain threshold, falling further behind.

I am open to using other controls (wxListCtrl, wxRichTextCtrl, etc).

+1  A: 

Have you considered limiting the amount of lines in the view? When we had a similar issue, we just made sure never more than 10,000 lines are in the view. If more lines come in at the bottom we remove lines at the top. This was not using WxWidgets, it was using a native Cocoa UI on Mac, but the issue is the same. If a styled text view (with colors, formatting and pretty printing) grows to large, appending more data at the bottom becomes pretty slow.

Mecki
A: 

Sounds like the control you are using is simply not built for the amount of data you are throwing at it. I would consider building a custom control. Here's some things you could take into account:

  1. When a new line comes in, you don't need to re-render the previous lines... they don't change and the layout won't change due to the new data.
  2. Try to only keep the visible portion plus a few screens of look-back in memory at a time. This would make it a little lighter... but you will have to do your own scroll management if you want the user to be able to scroll back further than your look-back and make it all appear to be seamless.
  3. Don't necessarily update one line at a time. When there is new data, grab it all and update. If you get 10 lines really quickly, and you update the screen all at once, you might save on some of the overhead of doing it line by line.

Hope this helps.

bobwienholt
A: 

Derive from wxVListBox. From the docs:

wxVListBox is a listbox-like control with the following two main differences from a regular listbox: it can have an arbitrarily huge number of items because it doesn't store them itself but uses OnDrawItem() callback to draw them (so it is a Virtual listbox) and its items can have variable height as determined by OnMeasureItem() (so it is also a listbox with the lines of Variable height).

sludge