User forums > Using Code::Blocks
High CPU usage
thomas:
This maybe?
--- Code: ---EVT_IDLE( CompilerGCC::OnIdle )
EVT_IDLE( DebuggerGDB::OnIdle )
--- End code ---
These plugins read stdout from processes they launch on a regular base triggered by a wxTimer (100ms). OnTimer() does not do anything except for calling wxWakeUpIdle(), and OnIdle() does the actual polling.
While moving the mouse, the system goes idle quite a few times, so it may be that OnIdle() is indeed called many, many times per second. At the very least, this means a lot of calls to wxProcess::IsInputAvailable() which calls wxStream::CanRead(). If there are actually processes running, two wxTextInputStreams are opened in addition, and one line is read from each.
I am not saying this *is* the actual cause, but it might just be. One should run gprof to see how often OnIdle() is really called. If it is 50 or 100 times per second, we have a culprit. In that case, have OnTimer() poll for input, which is better anyway, and remove OnIdle().
Even if it is not that, gprof will likely find some function that gets called amazingly often, providing a starting point for the search.
Michael:
Hello,
I have remarked the "same" high CPU usage with my configuration:
CodeBlocks 1.0-RC1-1 (all plugins + cache activated)
Windows XP Pro SP2
Pentium M 1,8 GHz
1024 MB RAM
Simply moving the mouse cursor on the CB window, the CPU usage rises around 20-30%, sometimes until more than 40%, other time around 10-20%.
Ad-Aware SE Personal rises the CPU usage until 11% and Windows Media Player until 10% approximately (just moving the mouse cursor at different speed and in/out the application window).
Therefore, CB increases the CPU usage around 2-4 times more (to confirm this result, it would be necessary to perform more comparisons and tests).
Anyway, I have not experienced particular problems using it and all seems to work well.
Best wishes,
Michael
rickg22:
OnIdle is safe to use... it's called only once per event cycle. In fact, it does what its name says: It's only activated when the system is IDLE.
But I'm not sure if the wakeupidle should be used...
In that case, I think OnIdle should use a counter or an internal timer to assure a MAXIMUM of calls per second.
Instead, if you use a timer instead of idle, you specify the EXACT number of times the routine will be called.
thomas:
The point I am having about OnIdle is that if you move your mouse, the OS generates a message, wakes up some thread to move the pointer, does some rectangle hit tests, possibly some MouseOver or MouseEnter/Leave messages are fired and processed, which alltogether goes rather quick (few dozen microseconds?), and then the system *goes idle* again.
If you move your mouse over a window and dump all WM_MOUSEMOVE notifications to a console, you get an idea about how many messages Windows(R) creates... 30-50 per second is not unusual. That means that you call OnIdle quite a few times per second (unless wxWindows filters these).
That might indeed possibly be an issue. First, message queues are usually thread-safe (I don't actually know about wxWindows, but I strongly assume they are!), so handling 50 messages means acquiring and releasing 50 mutexes or semaphores (or locked atomic writes, whatever) as a basic overhead. This is particularly bad on a system with NUM_CPU > 1.
And second, while that may still not be an awful lot, there are still several library calls (IsInputAvailable, CanRead, ...) and allocations/deallocations of complex objects (wxTextInputStream, wxEvent), which are not free. All of these derive from wxObject, they run non-trivial constructors and have a chain of virtual destructors. This is not noticeable if you create a few objects once, but if you allocate/destroy a couple of them several dozen of times every second, it adds up, so the resulting payload is not necessarily trivial.
At the very least, it is worth looking at.
WakeupIdle, like the docs say, forces idle events to be fired, even if the system is idle already. However, this function is only called twice every 100 ms, and only while either a compile or the debugger is running, too, so that should not do much harm. Still, polling for input directly inside OnTimer would be more efficient. That would remove the necessity to have OnIdle at all, and it would remove posting and handling of one message per timer event, as well as the creation/destruction of half a dozen objects each time.
I believe that calling WakeupIdle is necessary with the current design, because otherwise you could not run the compiler and debugger plugin at the same time. Whichever comes first would steal the idle events from the respective other (unless explicitely calling Skip), and the other would never poll for input.
rickg22:
Is there a way to check the ellapsed time in milliseconds since the last idle event handled?
Also, something makes me think. Is there a point on doing these checks if NO compilation or debug session has been started yet? I think we need a couple of if's in there.
Hmmm....
--- Code: ---void CompilerGCC::OnIdle(wxIdleEvent& event)
{
if (m_Process && ((PipedProcess*)m_Process)->HasInput())
event.RequestMore();
else
event.Skip();
}
void CompilerGCC::OnTimer(wxTimerEvent& event)
{
wxWakeUpIdle();
}
--- End code ---
I think we should add an "if(m_Process)" before doing the wxWakeUpIdle, this would save us from creating an idle events chain. The same code applies for debuggergdb.
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version