High CPU usage of simple program - c++

The code below is for an empty window but shows relatively high CPU usage of 25% on my Intel i3. I also tried the setFramerateLimit with no change. Is there a way to reduce the CPU usage?
#include<SFML/Window.hpp>
void processEvents(sf::Window& window);
int main()
{
sf::Window window(sf::VideoMode(800, 600), "My Window", sf::Style::Close);
window.setVerticalSyncEnabled(true);
while (window.isOpen())
{
processEvents(window);
}
return 0;
}
void processEvents(sf::Window& window)
{
sf::Event event;
window.pollEvent(event);
switch (event.type)
{
case sf::Event::Closed:
window.close();
break;
}
}

Since you're not calling window.display() in the loop, there's noting to halt the thread for the appropriate amount of time, set with sf::RenderWindow::setVerticalSyncEnabled or sf::RenderWindow::setMaxFramerateLimit.
Try this:
while (window.isOpen())
{
processEvents(window);
// this makes the thread sleep
// (for ~16.7ms minus the time already spent since
// the previous window.display() if synced with 60FPS)
window.display();
}
From SFML Docs:
If a limit is set, the window will use a small delay after each call to display() to ensure that the current frame lasted long enough to match the framerate limit.

The issue is
while (window.isOpen())
{
processEvents(window);
}
Is a loop with no pause in it. Since an a loop like this normally consumes 100% of the CPU I would have to guess that you have a 4 core CPU so it is consuming one entire core which is 25% of the capacity of the CPU.
You could add a pause in the loop so it is not running 100% of the time or you could change the event handling all together.

Related

Using sleep() in game loop makes delta time unstable

I'm writing a game loop with sfml. When I don't make it sleep, time elapsed for each loop iteration is ~1ms. But when I add sleep(sleepTime) suddenly dt is high. I restart dt at the beginning of the loop but it seems that it adds last sleep time to it. What causes it?
sf::Clock clock;
float dt;
sf::Time sleepTime = sf::milliseconds(0);
while(m_Window.isOpen())
{
sf::Time elapsed = clock.restart();
dt = elapsed.asMilliseconds();
cout << "Elapsed: " << dt;
sf::Event event;
while(m_Window.pollEvent(event))
{
switch(event.type)
{
case sf::Event::Closed:
m_Window.close();
break;
}
}
sleepTime = sf::milliseconds(16 - dt);
float time = sleepTime.asMilliseconds();
cout << "\tSleep time: " << time << endl;
if(sleepTime >= sf::Time::Zero)
{
sf::sleep(sleepTime);
}
else
{
cout << "Shit." << endl;
}
Without sleep: https://aww.moe/sn1z0a.png
With sleep: https://aww.moe/7seof1.png
What you're trying to do – limiting the game to a specific framerate – is already built into SFML. Just call sf::Window::setFrameRateLimit() with your intended framerate as parameter and you're set. It's also possible to use vertical synchronization (by using sf::Window::setVerticalSyncEnabled()) to limit the number of frames/updates, although it's often considered a bad idea, since the game would also slow down if the target machine can't render at the desired framerate (or speed up for high end screens running at 120 or 140Hz).
However, you'll typically want to disconnect your game updates from your frame rate so the game doesn't slow down, even if the current machine can't update the screen fast enough.
The basic approach using SFML will typically look like this (this is from memory, so might include bugs or typos):
sf::Clock updateTimer; // Clock to monitor the time passed
sf::Time passedTime; // Accumulated game time
const sf::Time frameTime(sf::milliseconds(10)); // intended time per frame; here: 10ms
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
// Event handling
}
// First add the time passed
passedTime += updateClock.restart();
unsigned int numUpdates = 0; // Count the updates done
// As long as enough time passed, do an update
// Up to a specific maximum to avoid problems, e.g.
// the main thread was blocked or can't catch up
while (passedTime >= frameTime) {
if (numUpdates++ < 10) {
// Do your game update here
}
// Subtract the time we've "handled"
passedTime -= frameTime;
}
window.clear();
// Draw your game here
window.display();
}
The usage of numUpdates might not be clear at first, but just imagine a situation where the machine is barely able to run the desired 100 updates per second. If you're 20 updates behind (some hick-up or whatever) the machine will never be able to catch up again properly, causing heavy stuttering or the game becoming unresponsive.

What's the simples way of adjusting frame rate in c++?

I have a while loop which displays things on window using openGL, but the animation is too fast compared to how it runs on other computers, so I need something in the loop which will allow to display only 1/40 seconds after previous display, how do I do that? (I'm c++ noob)
You need to check the time at the beginning of you loop, check the time again at the end of the loop after you've finished all of your rendering and update logic and then Sleep() for the difference between the elapsed time and the target frame time (25ms for 40 fps).
This is some code I used in C++ with the SDL library. Basically you need to have a function to start a timer at the start of your loop (StartFpsTimer()) and a function to wait enough time till the next frame is due based on the constant frame rate that you want to have (WaitTillNextFrame()).
The m_oTimer object is a simple timer object that you can start, stop, pause.
GAME_ENGINE_FPS is the frame rate that you would like to have.
// Sets the timer for the main loop
void StartFpsTimer()
{
m_oTimer.Start();
}
// Waits till the next frame is due (to call the loop at regular intervals)
void WaitTillNextFrame()
{
if(this->m_oTimer.GetTicks() < 1000.0 / GAME_ENGINE_FPS) {
delay((1000.0 / GAME_ENGINE_FPS) - m_oTimer.GetTicks());
}
}
while (this->IsRunning())
{
// Starts the fps timer
this->StartFpsTimer();
// Input
this->HandleEvents();
// Logic
this->Update();
// Rendering
this->Draw();
// Wait till the next frame
this->WaitTillNextFrame();
}

Wish To Execute A Function Periodically But Continue With The Rest Of Program Loop

Currently my program consists of a main loop which executes whilst a window is open. Inside the loop there is a function which must execute periodically (say every second or so), BUT the rest of the main loop has to continue executing and the loop to repeat without the periodic function being executed until the time is up. My question is - how can you execute the function periodically in the main loop without halting program execution altogether? Here is the code:
//Prototypes
void functionToBeExecutedPeriodically();
void someFunc1();
void someFunc2();
int main()
{
while (window.isOpen())
{
functionToBeExecutedPeriodically();
//This part of the loop must continue executing whilst the above
//idles for a limited period of time
someFunc1();
someFunc2();
window.display();
}
}
With a timer for example:
int main() {
sf::Clock timer;
while (window.isOpen()) {
if (timer.getElapsedTime() >= sf::seconds(1.0f)) {
functionToBeExecutedPeriodically();
timer.restart();
}
someFunc1();
someFunc2();
window.display();
}
}
That would execute the function every second.

A faster thread blocks slower thread

I'm working on a point cloud viewer, and my design is based on two thread
first thread updates the point cloud data ( about 10 fps)
second thread is a D3D renderer to render the point set to screen (about 90 fps)
so my code looks like this:
std::shared_ptr<PointCloud> pointcloud;
CRITICAL_SECTION updateLock;
void FirstThreadProc()
{
while(true)
{
/* some algorithm processes point cloud, takes time */
EnterCriticalSection(&updateLock);
pointcloud->Update(data,length,...); //also takes time to copy and process
LeaveCriticalSection(&updateLock);
}
}
/*...*/
std::shared_ptr<D3DRenderer> renderer;
void SecondThreadProc()
{
MSG msg = { 0 };
while (WM_QUIT != msg.message)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
EnterCriticalSection(&updateLock);
renderer->Render(pointcloud);
LeaveCriticalSection(&updateLock);
}
}
}
I was thought that the second thread is way more fast than first one, so when first one entered the critical section, the second one is blocked, so the renderer window should freeze now or then. but what i'm observed right now is that the renderer window runs very smooth, camera rotate or zoom in/out, all good, but the first thread is very unstable, its fps is ranging from 10 fps to 1 fps.
I'm thinking about two point cloud buffers, then first thread updates the second buffer when outsides the critical section, then swap two buffers within critical section. Will it work?
As mentioned in this, CRITICAL_SECTION is not provide first-in, first-out(FIFO) ordering. since the second thread is way more fast than the first thread, and its whole loop is critical section, it will enter the critical section right after leave it. This may always in the critical section and keep the first one out of it.
my solution is to put more job of the second thread outside the critical section, then it works fine.

Using boost::thread in a planet simulator

I am making a simulator of planets in space, and the issue is, that I cannot simulate more than ~100 planets, because the simulation slows down exponentially. To solve this problem, I thought using threads could solve my problem, since I am probably not experienced enaugh to use graphic card processors to calculate.
I have 2 functions in my program wich are used to calculate the gravitational force between planets and another one to check for collisions. I implemented threads in a way, so I calculate gravitational forces in one thread and collisions in another.
The problem is that the simulation isn't running any faster then without using threads. Maybe I'm implementing them wrong?
int main()
{
int numOfPlanets;
cout << "Enter the maximum number of planets to generate: ";
cin >> numOfPlanets;
App.Create(sf::VideoMode(1366, 740), "SFML Galaxy Simulator");
App.Clear(sf::Color(20,20,20));
generateRandomPlanets(500, 500, numOfPlanets);
//createPlanet(planets, sf::Vector2f(500,500), sf::Vector2f(0,0), 5, 500);
thread thread_1;
thread thread_2;
while(App.IsOpened())
{
sf::Event Event;
while (App.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
App.Close();
}
App.Clear(sf::Color(20,20,20));
thread_1 = thread(checkCollision);
thread_2 = thread(calculateForce);
thread_1.join();
thread_2.join();
updatePlanets();
App.Display();
}
thread_2.join();
thread_1.join();
return 0;
}
thread_1 = thread(checkCollision);
thread_2 = thread(calculateForce);
thread_1.join();
thread_2.join();
updatePlanets();
This launches two new threads to do some work in parallel, then blocks waiting for them to finish, then afterwards runs updatePlanets. You probably want:
thread_1 = thread(checkCollision);
thread_2 = thread(calculateForce);
updatePlanets();
thread_1.join();
thread_2.join();
This will run the three functions in parallel.
Also, this is an error at the end of main:
thread_2.join();
thread_1.join();
return 0;
You've already joined the threads, you can't join them again.
There's actually no point in declaring thread_1 and thread_2 outside the loop and reusing them, you could just declare them in the loop:
thread thread_1(checkCollision);
thread thread_2(calculateForce);
updatePlanets();
thread_1.join();
thread_2.join();
Also be aware that if updatePlanets throws an exception it will terminate your program because the thread_2 destructor will run while the thread is joinable and so call terminate(), which may be OK in this program, but is something to bear in mind.
I have made some more research after posting the question and found out that the main problem in the performance of my simulation was the time complexity of the algorithm for calculating gravitational forces of each planet relative to all other planets which was O(n^2).
I found out, that one or maybe the best method to approach this is by using Barnes-Hut algorithm for n-body simulation with it's time complexity of O(n log n). The way this algorithm works is it divides all the planets into quadtree nodes and then calculates forces acording to the center-mass of each node.
So to add all this together, using Barnes-Hut algorithm together with threading is the best way to approach this problem.