Same project I've been working on. It works nicely, does what I want it to.
However, being a real-time application, a lot of the time it spends is usually wasted CPU time. It has to act when the user does something, and we're pretty slow compared to the CPU (unless you can click the mouse at 3GHz).
Without any sort of 'sleeping', the CPU usage seems to sit anywhere from 0.5% to 3%. It doesn't seem like much, but on a lower-end computer it probably would make a difference, and many other highly-interactive applications use less CPU time. Additionally, this is with a pretty minimal number of things going on. It's just unit testing at this point.
I can make the main thread sleep, and that seems to lower the CPU usage down to around a maximum of 1.3%. It rarely goes above 1%. The RAM usage isn't abysmally high - somewhere around 30MB - I'm trying to keep the memory impact as low as I can.
There's one big main loop that runs in the main thread, and I think I've cut the number of computations in half. Instead it'll determine which computations to perform and only perform those. That seems to save some CPU time.
I can just use the standard "std::this_thread::sleep_for" and it cuts down CPU time, but I don't know if that's even a decent decision. As it stands right now, this application is not multi-threaded, but it is my intention to add support for multi-threading in the future, after the project is stable. This would drastically hurt that support. There's no way I could also make all the other threads sleep as well. And I don't know how I'd make it thread-safe while also making the main thread sleep with the other working threads active.
I haven't noticed any negative impact on interactivity with just making the thread sleep after every loop iteration, but I feel like that would really hurt multi-threading. I know there are many loop iterations where the application just 'spins' and doesn't do anything.
Do any of you have any ideas on how I could cut CPU usage but also leave it open for future multi-threading support?
Without seeing the code it's hard to know the right answer, but I can offer a few suggestions.
Sleeping makes sense if what you're doing is tied to real time. For example, if you need to update a simulation every 10ms then you'd probably sleep between updates.
What's more common is to be waiting for some event to occur like a mouse click, a key press, or a message from another thread. For this you need a mutex variable, or condition wait variable, etc. Unfortunately, I don't know if the latest standards support these or if you'll have to use the OS support directly.
Without knowing more about your application, what OS, what libraries (SFML, etc, if any), it's pretty hard to make any comments.
Having written many massively multi-threaded applications, I can tell you that putting a sleep call in a thread is generally the wrong answer. That will reduce the responsiveness of the thread. When a thread is "not doing anything", it should be waiting on an event of some sort.
Generally, the only time I use sleep within a thread is when an external entity (another server or process) is down. Sleep allow the thread to check the external once every 30 seconds or so (configurable of course) rather than slamming it continuously.
In my experience, if a thread is not designed to wait on an event, process the event, then wait for the next event, the design is probably wrong.
If your threads are all truly event driven, then I would run a code profiler and see where your threads are spending their time.
I was sort of thinking a similar idea. I want events like mouse clicks, key presses, etc, to trigger the action, not sit around waiting for it to happen.
I can't with full confidence say if C++ supports exactly those things, but this is what I've found:
I've used condition variables in C, in my operating systems class, for real-time programs, but never in C++. C is also an entirely different monster, and I'm still making the transition from C bootcamp back to C++.
I've noticed that CPU usage goes up when handling events triggered in rapid succession, but having the window sit there and do nothing uses very little resources (CPU utilization will drop to 0%-0.3%).
I've tried to make it as event-driven as possible, but part of my code does need to wait for something to happen. It'll poll an event, take action, and then poll the next. It won't do anything if there isn't an event.
If helps, I'm using SFML to capture events. The only real multi-threading I've done is in operating systems, which does not have any graphical component, and it used a lot of mutexes and condition variables to have a thread be "woken up" when something happened that it needed to take care of.
I don't know if a similar sort of design is advisable here. I've made my code as modular as possible, so changing exactly how event callbacks are triggered is pretty simple.
If you're polling for events, that's going to be more expensive than triggering a thread when an event occurs.
Unless the polling code has some mechanism built in to wait for events, you can be CPU bound there. Putting a call to sleep in the polling loop is not the right answer. That will reduce the responsiveness of responding to events.
What you really want is for threads to be dedicated to specific event types (mouse click, keypress, etc). The first thing the thread does is issue a wait on the event type. When the event occurs, the thread wakes up, processes the event and loops back to the wait on event type. That's an oversimplification of course, because in reality threads have to sensitive to multiple events. i.e. A mouse click, or shutdown message, or possibly a timer pop. You get the idea.
You're totally right. I went about the design wrong. Thankfully, I found the API documentation for a wait-implemented event thread. Thankfully, it'll only require a couple lines of code to be changed.
Nothing else will have to be changed, especially since everything else is triggered only when an event occurs. That should remove the need for manually sleeping the main thread, which is one reason why I asked here - I wanted to find a way to lower CPU usage and not reduce responsiveness.
I'm adding my own events, but those are combinations of captured events and recorded event history (like a mouse down being true and a "mouse moved" event would be sent out to the other threads as a "mouseDrag" event), but those I'm adding for convenience of taking the work from them about determining user action and moving that to the event handler.
Hopefully, I should see the CPU utilization go down. Right now, the whole thing is single-threaded, but I'm working on splitting up threads as I refactor.
Thanks for the input! There's absolutely no reason to have my event handler poll-based - it'll be switched to wait for events and sleep until one is triggered.
I do have another inquiry: what do you think would be the best approach to lock working threads from modifying data while other threads are operating on it? I have a renderer, and I wouldn't want the underlying data to be modified before everything was rendered.
Would condition variables and mutexes be my best option there?