wxDC Performance OSX (CPU Hog)

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
Post Reply
Bartvanstiphout
Earned a small fee
Earned a small fee
Posts: 12
Joined: Thu Mar 26, 2009 9:03 pm

wxDC Performance OSX (CPU Hog)

Post by Bartvanstiphout »

Hello all,

In my application I use a large panel with a wxDC to draw on. I refresh the screen every 50ms to render about 20fps. On windows (retina, emulated with parallels desktop) this application consumes about 7% CPU. In the OSX version (MacBook Pro 2017 TouchBar, running High Sierra), the CPU load is 109%. I tested the various render loops samples described here: https://wiki.wxwidgets.org/Making_a_render_loop, but they all become a CPU hog when de canvas is dragged bigger. Is there another option I've missed out? Do other users experience the same drastic performance difference?

Thanks in advance,

Bart
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDC Performance OSX (CPU Hog)

Post by doublemax »

Disclaimer: I don't use OSX and can't test this.

Which wxWidgets version are you using?

I've never read about a similar problem, so i don't think there is a general problem. Can you profile the code and identify any hot spots?

If not, try commenting out parts of the drawing code, maybe you can isolate one particular operation responsible for the slow down.
Use the source, Luke!
Bartvanstiphout
Earned a small fee
Earned a small fee
Posts: 12
Joined: Thu Mar 26, 2009 9:03 pm

Re: wxDC Performance OSX (CPU Hog)

Post by Bartvanstiphout »

Thanks for your reply doublemax.

I've tested it with version 3.0.3 & the 3.1.0, the exact samples as described on the Renderloop page.

Time profiling the render loop with a fixed timer shows me this:
Image

The sample is already very minimal. I tried only calling Refresh(), and disabling the OnPaint event. This still gives me the high cpu load, even when nothing happens!

Hope this helps..

It would be great if another OSX user can confirm this behaviour, as a starting point.

Thanks,

Bart
Last edited by Bartvanstiphout on Sat Dec 23, 2017 6:02 pm, edited 1 time in total.
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDC Performance OSX (CPU Hog)

Post by doublemax »

Can you give a general outline of what you're doing inside the paint event handler?
Or does it even happen if you don't draw anything?

What's the timer frequency?
Use the source, Luke!
Bartvanstiphout
Earned a small fee
Earned a small fee
Posts: 12
Joined: Thu Mar 26, 2009 9:03 pm

Re: wxDC Performance OSX (CPU Hog)

Post by Bartvanstiphout »

The timer in the sample fires every 10ms, but even when it fires every 20ms, the CPU exceeds 100%, in contrary to the windows version (<10%).
When I comment out the OnPaint event in the EventTable, it still goes to 150% when I maximize the canvas.

The render code isn't that shocking..:

Code: Select all

void BasicDrawPane::render( wxDC& dc )
{
	static int y = 0;
	static int y_speed = 2;
 
	y += y_speed;
	if(y<0) y_speed = 2;
	if(y>200) y_speed = -2;
 
	dc.SetBackground( *wxWHITE_BRUSH );
	dc.Clear();
	dc.DrawText(wxT("Testing"), 40, y);
}
Here is the full code of the timer render sample found at https://wiki.wxwidgets.org/Making_a_render_loop:

Code: Select all

#include <wx/sizer.h>
#include <wx/wx.h>
#include <wx/timer.h>
 
class BasicDrawPane;
 
class RenderTimer : public wxTimer
{
    BasicDrawPane* pane;
public:
    RenderTimer(BasicDrawPane* pane);
    void Notify();
    void start();
};
 
 
class BasicDrawPane : public wxPanel
{
 
public:
    BasicDrawPane(wxFrame* parent);
 
    void paintEvent(wxPaintEvent& evt);
    void paintNow();
    void render( wxDC& dc );
 
    DECLARE_EVENT_TABLE()
};
 
class MyFrame;
 
class MyApp: public wxApp
{
    bool OnInit();
 
    MyFrame* frame;
public:
 
};
 
 
RenderTimer::RenderTimer(BasicDrawPane* pane) : wxTimer()
{
    RenderTimer::pane = pane;
}
 
void RenderTimer::Notify()
{
    pane->Refresh();
}
 
void RenderTimer::start()
{
    wxTimer::Start(10);
}
 
IMPLEMENT_APP(MyApp)
 
class MyFrame : public wxFrame
{
    RenderTimer* timer;
    BasicDrawPane* drawPane;
 
public:
    MyFrame() : wxFrame((wxFrame *)NULL, -1,  wxT("Hello wxDC"), wxPoint(50,50), wxSize(400,200))
    {
        wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
        drawPane = new BasicDrawPane( this );
        sizer->Add(drawPane, 1, wxEXPAND);
        SetSizer(sizer);
 
        timer = new RenderTimer(drawPane);
        Show();
        timer->start();
    }
    ~MyFrame()
    {
        delete timer;
    }
    void onClose(wxCloseEvent& evt)
    {
        timer->Stop();
        evt.Skip();
    }
    DECLARE_EVENT_TABLE()
};
 
 
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_CLOSE(MyFrame::onClose)
END_EVENT_TABLE()
 
bool MyApp::OnInit()
{
    frame = new MyFrame();
    frame->Show();
 
    return true;
} 
 
 
BEGIN_EVENT_TABLE(BasicDrawPane, wxPanel)
EVT_PAINT(BasicDrawPane::paintEvent)
END_EVENT_TABLE()
 
 
 
BasicDrawPane::BasicDrawPane(wxFrame* parent) :
wxPanel(parent)
{
}
 
void BasicDrawPane::paintEvent(wxPaintEvent& evt)
{
    wxPaintDC dc(this);
    render(dc);
}
 
void BasicDrawPane::paintNow()
{
    wxClientDC dc(this);
    render(dc);
}
 
void BasicDrawPane::render( wxDC& dc )
{
    static int y = 0;
    static int y_speed = 2;
 
    y += y_speed;
    if(y<0) y_speed = 2;
    if(y>200) y_speed = -2;
 
    dc.SetBackground( *wxWHITE_BRUSH );
    dc.Clear();
    dc.DrawText(wxT("Testing"), 40, y); 
}
Thanks
User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: wxDC Performance OSX (CPU Hog)

Post by eranon »

Bartvanstiphout wrote:It would be great if another OSX user can confirm this behaviour, as a starting point.
I can run a test on 10.9, 10.10 and 10.12 (my 10.11 is currently broken and 10.13 is in my TODO list) if you want.
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]
Bartvanstiphout
Earned a small fee
Earned a small fee
Posts: 12
Joined: Thu Mar 26, 2009 9:03 pm

Re: wxDC Performance OSX (CPU Hog)

Post by Bartvanstiphout »

Yes please!

I wonder if it is related to this: https://trac.wxwidgets.org/ticket/17439?

Thanks,

Bart
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDC Performance OSX (CPU Hog)

Post by doublemax »

With that simple drawing code, i can only assume that the problem lies somewhere else. What happens if you disable the timer or the paint event handler?

Can you try the sample from here?
viewtopic.php?p=181028#p181028

It was for another purpose, but it contains a small animation and is based on the "minimal" sample that comes with wxWidgets.
Use the source, Luke!
User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: wxDC Performance OSX (CPU Hog)

Post by eranon »

Bartvanstiphout wrote:Yes please!
Yes, but you have to provide your built test app to run the same copie (knowing it can be due to compiler, IDE, build options, a precise wxWidgets version, underlying SDK...). And if you want I sample from the activity monitor, a debug one will be better, of course.
Last edited by eranon on Sat Dec 23, 2017 8:31 pm, edited 1 time in total.
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]
Bartvanstiphout
Earned a small fee
Earned a small fee
Posts: 12
Joined: Thu Mar 26, 2009 9:03 pm

Re: wxDC Performance OSX (CPU Hog)

Post by Bartvanstiphout »

Doublemax, the sample you have provided consumes about 45% CPU, and that is even with a small canvas since this one was not resizable!

Eranon, a binary can be found here:
https://www.dropbox.com/s/bvh0gewg456gd ... t.zip?dl=1

Thanks all,

Bart
User avatar
doublemax
Moderator
Moderator
Posts: 19116
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDC Performance OSX (CPU Hog)

Post by doublemax »

Doublemax, the sample you have provided consumes about 45% CPU, and that is even with a small canvas since this one was not resizable!
The frame was resizable.

Anyway, 45% is still too much, maybe the trac ticket you mentioned is indeed describing the same problem.
Use the source, Luke!
User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: wxDC Performance OSX (CPU Hog)

Post by eranon »

OK, here are my tests using your DCtest.app:
snap_0005237.png
snap_0005237.png (6.52 KiB) Viewed 3432 times
Also, not seen any obvious hog function or thread in sampling graph.
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]
Skip
In need of some credit
In need of some credit
Posts: 1
Joined: Tue Jan 09, 2018 3:26 pm

Re: wxDC Performance OSX (CPU Hog)

Post by Skip »

I am also experiencing the same problem, and when running the application bartvanstiphout provided my processor load is the following:

-Not resized on hd screen: 14%
-Not resized on retina screen: 19%
-Fit to screen on hd screen: 59%
-Fit to screen on retina screen: 125%

As this DC is indeed very simple, we can't expect this happening. When I run the profiler on the code that was mentioned above, I see 7 or 8 threads that are busy with __vImageCopyBuffer functions, that originate from Apple's Accelerate framework. The main thread is also busy with some Apple function. (see both screenshots below)
Schermafbeelding 2018-01-09 om 14.54.37.png
^worker thread
Schermafbeelding 2018-01-09 om 16.39.57.png
^main thread
Post Reply