September 02, 2019

C++ is performing poor in a starfield simulation

The naive assumption was, that the C++ programming language together with the SFML library performs very well of ressource intensive tasks. So I've created a simple multi-agent simulation which contains of some circles on the screen who are moving towards a goal. The program follows the normal pattern of SFML programming and contains of a GUI for painting the graphics and physics backend which is adjusting the position.

// g++ -std=c++14 -lsfml-graphics -lsfml-window -lsfml-system
#include SFML/Graphics.hpp
#include iostream
#include random

// global function
int random_integer(int min, int max) {
    return min + rand() % (( max + 1 ) - min); // fast random generator
}

class Robot {
public:
  sf::Vector2f pos;
  sf::Vector2f goal;
  
  void move() {
    int diffx=goal.x-pos.x;
    if (diffx>0) diffx=1;
    if (diffx<0) diffx=-1;
    if (diffx==0) diffx=0;
    int diffy=goal.y-pos.y;
    if (diffy>0) diffy=1;
    if (diffy<0) diffy=-1;
    if (diffy==0) diffy=0;
    pos=sf::Vector2f(pos.x+diffx,pos.y+diffy);
  }
  void setgoal() {
    goal=sf::Vector2f(random_integer(0,600),random_integer(0,400));
  }
  void update() {
    move();
    if (pos==goal)
      setgoal();
  }
};

class Physics {
public:
  std::vector myrobot;
  unsigned numberrobot=5;
  void update() {
    for (unsigned i=0;i

With only five robots on the screen the performence is well. According to the Fedora taskmanager the program occupies 3% of the CPU which is better than a Python program would need. I was confident, that C++ is the perfect language for a multi-agent simulation.



After increasing the amount of robots on the screen to a higher value the performance was reduced massively. In the second trial, 500 robots are shown at the screen and the cpu consumption is 25%. While in the third example 3000 robots are painted to the screen and are producing a load of 43% to the CPU.



Only to get an impression for the relation. The SFML window has a size of 600x400 pixel which is equal to 240000 pixel. That means, if a single robot needs 1 pixel around 240000 robots can be displayed at the same time on the window. But the small amount of 3000 robots are too much for the C++ engine and producing a high workload.

I'm not sure, if the program can be made more efficient. The algorithm itself is supersimple. Every frame the physics engine is calculating the new position of a robot which is not very ressource intensive. It seems, that the SFML painting method is the bottleneck. Perhaps it's possible to improve the speed by painting the robots first on hidden surface and the blit the surface to the screen. The other option is, that with the sourcecode everything is fine, but the C++ language is not fast enough.

Update

According to the SFML handbook it's possible to draw on a hidden texture surface first and then blit the texture to the window.


// texture drawing
    renderTexture.display();
    const sf::Texture& texture = renderTexture.getTexture();
    sf::Sprite sprite(texture);
    window.draw(sprite);
Technically it works, because all the circles are visible with the procedure to the screen too. Unfortunately the performance is the same like drawing the circles directly to the SFML window. Here again the comparison: window size: 600x400 pixel, 240000 total framerate 40 frame per second 5 robots on the screen, 3% cpu consumption 500 robots on the screen, 25% cpu consumption 2000 robots on the screen, 43% cpu consumption Literature
I'm not the first guy who has problems with drawing a particle simulation with SFML. Here https://en.sfml-dev.org/forums/index.php?topic=4295.0 is a thread about drawing thousands of sprites at the same time. The problem is well known and is called a low framerate. It seems, that in the SFML library there is a bottleneck which prevents the user to draw many sprites at the same time to the GPU.

It seems, that from a technical point of view, the bottleneck can be avoided but not with the normal SFML toolset. If the combination of C++ plus SFML doesn't result into a high efficiency, it make sense to switch back to Python. The advantage is, that nobody is surprised if the pygame rendering engine is too slow to draw more than one hundred particles at the same time to the screen.