Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Confused About Performance  (Read 7540 times)

0 Members and 1 Guest are viewing this topic.

omariisan

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Confused About Performance
« on: February 05, 2014, 05:28:41 pm »
Hi.

I use Game Maker: Studio quite a bit for prototyping and rapid development, but I also have some experience with C++ and Python. I've been playing with SFML and implemented a window, sprite, and keyboard movement. It's all very basic. However, I've noticed that my Game Maker: Studio project runs at about 1000FPS on my hardware. Pretty damn fast. I figured a game written and compiled in C++ would be just a good, if not better (Game Maker: Studio uses a scripting language called GML). At 640x480, drawing one sprite, without double buffering or anything like that, I get about 950-960 FPS. Okay, so far so good. I'm surprised it's a bit lower, but it's not a big deal. However, when I maximize the window, I drop to 260 FPS. Again, this is while only drawing a single 32x32 image. Game Maker: Studio does not seem to suffer from this issue. My PySFML version, nets me about 350 FPS (it's about half as fast as the C++ version from what I can tell), but drops down to 150 FPS when I maximize the window.

I am lead to believe I have implemented something incorrectly, as such pitiful framerates without much drawing going on make the prospect of developing a full project dubious at best.

I've included the draw method from my C++ method. As you can see I also draw text to the screen in both versions. I am not the best C++ programmer, so I apologize if it's painful to read.

void Game::draw() {
    fpsDrawLoopCounter++;
    window.clear();
    std::vector<GameObject *>::const_iterator it = world.get_objectList().begin();
    while (it != world.get_objectList().end()) {
        window.draw((**it).get_sprite());
        ++it;
    }
    std::stringstream ss;
    ss << "FPS: " << lastReportedFPS << std::endl;
    if (state == State::PAUSED) {
        ss << "PAUSED" << std::endl;
    }
    sf::Text fpsText(ss.str(), systemFont, 16);
    fpsText.setPosition(10, 10);
    window.draw(fpsText);
    window.display();
}

Beyond this there is not much going on.

Lo-X

  • Hero Member
  • *****
  • Posts: 618
    • View Profile
    • My personal website, with CV, portfolio and projects
Re: Confused About Performance
« Reply #1 on: February 05, 2014, 05:47:22 pm »
without any information about you computer, your whole code, vertical-sync, etc. we can't say much.

But 200+ fps is quite good (even more than enough) and it shouldn't drop much if you do nothing wrong.

omariisan

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Confused About Performance
« Reply #2 on: February 05, 2014, 06:13:54 pm »
Vsync is disabled. The CPU is an A6-4400M (2.7Ghz). The GPU is a dual-graphics setup, with an HD 7520G + HD 7470 M. But, regardless, my issue isn't that SFML is performing poorly (200 FPS is fine and dandy); it's that it is performing extremely poorly relative to another program that should, in theory, be slower, despite the fact that it is actually doing even less. I will post the relevant sections of code below. Some things are commented out because they are disabled for testing purposes.

Initialization

#include "Game.h"
#include <iostream>
#include "GameObject.h"
#include "Player.h"
#include <sstream>

Game::Game() :
    state(State::PLAYING),
    window(sf::VideoMode(640, 480), "SFML window"),
    renderTexture(),
    renderSprite(),
    tickRate(30),
    fpsLimit(0),
    fpsUpdateTicker(0),
    fpsUpdateRate(0.5),
    fpsDrawLoopCounter(0),
    vSyncOn(false),
    gameUpdateTicker(0),
    secondsPassed(0),
    isRunning(true),
    gameClock(),
    world(),
    lastReportedFPS(0) {
    window.setFramerateLimit(fpsLimit);
    window.setVerticalSyncEnabled(vSyncOn);
    systemFont.loadFromFile("fonts/Arcadepix Plus.ttf");
}

Basic game loop

void Game::play() {
    state = State::PLAYING;
    while(isRunning) {
        secondsPassed = gameClock.getElapsedTime().asSeconds();
        gameClock.restart();
        //input();
        if (state == State::PLAYING) {
            gameUpdateTicker += secondsPassed;
            while (gameUpdateTicker >= 1.0 / tickRate) {
                gameUpdateTicker -= 1.0 / tickRate;
                //update();
            }
        } else if (state == State::PAUSED) {
            //pause the game
        }
        draw();
        fpsUpdate();
    }
    quit();
}

Draw function
void Game::draw() {
    fpsDrawLoopCounter++;
    window.clear();
    std::vector<GameObject *>::const_iterator it = world.get_objectList().begin();
    while (it != world.get_objectList().end()) {
        window.draw((**it).get_sprite());
        ++it;
    }
    std::stringstream ss;
    ss << "FPS: " << lastReportedFPS << std::endl;
    if (state == State::PAUSED) {
        ss << "PAUSED" << std::endl;
    }
    sf::Text fpsText(ss.str(), systemFont, 16);
    fpsText.setPosition(10, 10);
    window.draw(fpsText);
    window.display();
}

FPS counter

void Game::fpsUpdate() {
    fpsUpdateTicker += secondsPassed;
    if (fpsUpdateTicker > fpsUpdateRate) {
        fpsUpdateTicker -= fpsUpdateRate;
        lastReportedFPS = fpsDrawLoopCounter / fpsUpdateRate;
        fpsDrawLoopCounter = 0;
    }
}
 

Nothing else effects the code in a meaningful way. a Game object is created and .play() is called.

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Re: Confused About Performance
« Reply #3 on: February 05, 2014, 08:09:14 pm »
My only comment is to advice you to stop thinking in FPS, forget they exist. They are not an effective metric for almost anything.

Measure frame time, and work with that, that will tell you better how efficient rendering is being. In such simple cases, where the FPS are so high, they lose the meaning even more.

GML should be fine and have a decent performance, as well as SFML, its all more than enough for your needs(most likely).

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Confused About Performance
« Reply #4 on: February 05, 2014, 10:03:52 pm »
I've no idea how Game Maker works in the background, but since they are two different things a direct comparison is kind of flawed from the beginning.
I assume Game Maker use the GPU right?

At first you should make sure that your graphic drivers are up-to-date. If you're running on the wrong or old drivers performance will suffer.
Next you can simply run your application through a profiler to see where most of the time is wasted. If it's in some cryptic OpenGL function, then chances are high, that your GPU driver is "buggy".

And as kind of pointed out by others, FPS is not linear at all. If you think things are really bad because of one sprite and that it will get equally worse for another sprite, you're wrong. The FPS won't drop drastically at the lower ends. To prevent this kind of thinking, one can as Grimshaw said, turn to frame time.

Just because you're using a library and it performance worse than something else, it doesn't necessarily have to be the library itself or even the programming language. Chances are higher that it's a driver issue. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Re: Confused About Performance
« Reply #5 on: February 05, 2014, 10:29:38 pm »
Although there are some things you could do to speed it up slightly, like use a vertex array, build in release mode, make sure you aren't copying unnecessary things every frame, caching Fps text and updating every few frames, etc., I wonder if the difference is due to your display driver converting OpenGL calls to directx.

Hmmz

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Confused About Performance
« Reply #6 on: February 06, 2014, 05:05:36 pm »
I really doubt that it could be the bottleneck, but stringstream is slow as heck.

SLC

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: Confused About Performance
« Reply #7 on: February 06, 2014, 06:31:44 pm »
Have you taken into consideration that Game Maker: Studio could be using Multithreading, GPU Computing (on supported hardware) and everything that allows it to compute faster (like SSE SIMD)? While your program it's just an infinite loop with unoptimized C++ code that uses just a single core of your CPU. I'm not an expert on the matter but keep in mind that Game Maker: Studio is a paid software which enables it's experienced dedicated programmers to exploit every bit of performance gain during run-time. And if it's scripting languages uses a JIT compiler (which I think it does) then the scripts become as fast as C++.

You just can't compare your app with a Game Maker: Studio app. It's not SFML's fault on performance since it's you that's writing the app and SFML just provides wrappers of the low level system functionality.

Just open a Game Maker: Studio app and see how many CPU cores it uses. If the application needs allot of processing power the I bet you'll see 100% CPU usage on your system (because it uses all the CPU cores) and then open your application (which must also do some intensive calculations) and check the CPU usage again and you'll see it doesn't go above 50% (because it uses only one CPU core).

Turbine

  • Full Member
  • ***
  • Posts: 100
    • View Profile
Re: Confused About Performance
« Reply #8 on: February 10, 2014, 12:35:36 pm »
Oh dear. Lets set you straight.

There's a few things you have to consider now, with the fairly recent changes I've heard from people about Game Maker Studio.

You cannot really compare the fps of the two, just trust us on this one. Additionally GM is using direct x instead of opengl, which to be honest is quicker on Windows, but don't take this as SFML is worse than GM. There's a bit more too it than pure graphics performance.

It is true that GM now generates C++ code and compiles it from the project, but that does not make it faster than a typical C++ game project.

GM is an engine, with it's own very limited language. Doing anything outside of the norm or something low level just doesn't work out well. You have far greater potential for cpu performance and code quality using C++ and SFMl than you would with GM. Graphically, a well designed game could use SFML without any performance problems for the user, for instance, say you were to draw an image 10,000 times and comparing it to XNA or something using direct x. While it's nice to have, it's not generally necessary to draw things this many times.

I'd say C++ gives you the tools to create a well designed (from a code perspective), great performing, flexible and efficient way to create the underlying game. SFML provides access to non-cpu bound tasks, as well as provide a simple, cross-platform layer for easy implementation of these features.

Compare cpu & gpu utilisation and memory usage instead.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Confused About Performance
« Reply #9 on: February 10, 2014, 03:29:55 pm »
So much esoteric discussion here... yes it is true that Game Maker does a lot of optimisation for you, but that doesn't mean that you can't produce comparable performance with your own code... even if you aren't a professional.

Here are the more or less optimised code fragments for you:
    void Game::play() {
        state = State::PLAYING;
        while(isRunning) {
            secondsPassed = gameClock.restart().asSeconds(); // <-- move it here...
            //gameClock.restart();
            //input();
            if (state == State::PLAYING) {
                gameUpdateTicker += secondsPassed;
                while (gameUpdateTicker >= 1.0 / tickRate) {
                    gameUpdateTicker -= 1.0 / tickRate;
                    //update();
                }
            } else if (state == State::PAUSED) {
                //pause the game
            }
            draw();
            fpsUpdate();
        }
        quit();
    }
    void Game::draw() {
        fpsDrawLoopCounter++;
        window.clear();
        //std::vector<GameObject *>::const_iterator it = world.get_objectList().begin();
        //while (it != world.get_objectList().end()) {
            //window.draw((**it).get_sprite());
            //++it;
        //}
        for (const auto& object : world.get_objectList()) { // Use C++11 range-for... better optimisation
             window.draw(object->get_sprite());// <-- I hope your get_sprite() is const...
        }
        // At this point you might also want to consider storing the GameObjects themselves
        // directly in the vector as opposed to merely pointers. It increases locality and might
        // improve FPS if that is a limiting factor.
        //std::stringstream ss; // Too much stringstream is unhealthy for FPS
        //ss << "FPS: " << lastReportedFPS << std::endl;
        //if (state == State::PAUSED) {
            //ss << "PAUSED" << std::endl;
        //}
        char fps_string[32]; // Use stack allocated char array instead :D
        snprintf(fps_string, 32, "FPS: %d\n%s", lastReportedFPS, (state == State::PAUSED) ? "PAUSED" : ""); // snprintf is C++11... change %d to %f if you are using floating point
        //sf::Text fpsText(fps_string, systemFont, 16); // <-- This is bad... try to move sf::Text declaration out of your loop and reuse it every frame...
        fpsText.setString(fps_string); // <-- Like this...
        //fpsText.setPosition(10, 10); // <-- Move this out of the loop as well... it always stays the same...
        window.draw(fpsText);
        window.display();
    }
Those are only a few of the more obvious optimisations I could think of... profiling would need to be conducted to enable more in depth optimisations and since you didn't provide all your code I could not do so...

The main idea was that you want to minimize unneeded execution time and more importantly memory access. Stack variables are much much faster than heap variables (or containers that allocate to the heap) and so prefer using them in critical areas. Also... try avoiding streams wherever possible... they are really slow compared to the rest of the standard library...
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re: Confused About Performance
« Reply #10 on: February 10, 2014, 09:19:37 pm »
I'd point out that I bet you were compiling in Debug mode, with compiler optimizations disabled. If you switched to Release and made sure compiler optimizations were enabled, I bet you'd see more of what you want to see.