【问题标题】:Simple C++ SFML program high CPU usage简单的 C++ SFML 程序 CPU 使用率高
【发布时间】:2014-04-03 10:40:55
【问题描述】:

我目前正在开发一个平台游戏并尝试实现一个时间步长,但是对于大于 60 的帧速率限制,CPU 使用率会从 1% 上升到 25% 甚至更多。

我制作了这个最小的程序来演示这个问题。代码中有两个 cmets(第 10-13 行、第 26-30 行)描述了问题和我测试过的内容。

请注意,FPS 的内容与问题无关(我认为)。

我尽量保持代码简短:

#include <memory>
#include <sstream>
#include <iomanip>
#include <SFML\Graphics.hpp>

int main() {
  // Window
  std::shared_ptr<sf::RenderWindow> window;
  window = std::make_shared<sf::RenderWindow>(sf::VideoMode(640, 480, 32), "Test", sf::Style::Close);
  /*
  When I use the setFramerateLimit() function below, the CPU usage is only 1% instead of 25%+
  (And only if I set the limit to 60 or less. For example 120 increases CPU usage to 25%+ again.)
  */
  //window->setFramerateLimit(60);

  // FPS text
  sf::Font font;
  font.loadFromFile("font.ttf");
  sf::Text fpsText("", font, 30);
  fpsText.setColor(sf::Color(0, 0, 0));

  // FPS
  float fps;
  sf::Clock fpsTimer;
  sf::Time fpsElapsedTime;
  /*
  When I set framerateLimit to 60 (or anything less than 60) 
  instead of 120, CPU usage goes down to 1%.
  When the limit is greater, in this case 120, CPU usage is 25%+
  */
  unsigned int framerateLimit = 120;
  sf::Time fpsStep = sf::milliseconds(1000 / framerateLimit);
  sf::Time fpsSleep;
  fpsTimer.restart();

  while (window->isOpen()) {
    // Update timer
    fpsElapsedTime = fpsTimer.restart();
    fps = 1000.0f / fpsElapsedTime.asMilliseconds();

    // Update FPS text
    std::stringstream ss;
    ss << "FPS: " << std::fixed << std::setprecision(0) << fps;
    fpsText.setString(ss.str());

    // Get events
    sf::Event evt;
    while (window->pollEvent(evt)) {
      switch (evt.type) {
      case sf::Event::Closed:
        window->close();
        break;
      default:
        break;
      }
    }

    // Draw
    window->clear(sf::Color(255, 255, 255));
    window->draw(fpsText);
    window->display();

    // Sleep
    fpsSleep = fpsStep - fpsTimer.getElapsedTime();
    if (fpsSleep.asMilliseconds() > 0) {
      sf::sleep(fpsSleep);
    }

  }

  return 0;
}

我不想使用 SFML 的 setFramerateLimit(),而是我自己的 sleep 实现,因为我将使用 fps 数据来更新我的物理和东西。

我的代码中是否存在逻辑错误?我看不到它,因为它的帧速率限制为例如 60(或更少)。是因为我有一个 60 Hz 的显示器吗?

PS:使用 SFML 的 window->setVerticalSync() 不会改变结果

【问题讨论】:

    标签: c++ cpu cpu-usage sfml frame-rate


    【解决方案1】:

    我用这个answer回答了另一个similar question

    问题是,它并不能完全帮助您降低 CPU 使用率,但我尝试了您的代码,它在 120 FPS(甚至更多)的 1% cpu 使用率下运行良好。当您使用“游戏循环”制作游戏或交互式媒体时,您不想因睡眠而损失性能,您希望使用计算机可以提供的尽可能多的 CPU 时间。除了休眠,您还可以处理其他数据,例如加载内容、寻路算法等,或者只是不限制渲染。

    我提供了一些有用的链接和代码,这里是:


    类似问题:Movement Without Framerate Limit C++ SFML

    您真正需要的是固定时间步长。看看SFML游戏 开发书source code。这是有趣的 sn-p Application.cpp:

    const sf::Time Game::TimePerFrame = sf::seconds(1.f/60.f);
    
    // ...
    
    sf::Clock clock;
    sf::Time timeSinceLastUpdate = sf::Time::Zero;
    while (mWindow.isOpen())
    {
        sf::Time elapsedTime = clock.restart();
        timeSinceLastUpdate += elapsedTime;
        while (timeSinceLastUpdate > TimePerFrame)
        {
            timeSinceLastUpdate -= TimePerFrame;
    
            processEvents();
            update(TimePerFrame);
    
        }
    
        updateStatistics(elapsedTime);
        render();
    }
    

    如果这不是您真正想要的,请参阅“Fix your timestep!” Laurent Gomila 本人在 SFML 论坛中链接。

    【讨论】:

    • 谢谢你! (这么晚才回复很抱歉)。关于您的代码的一个问题:我是否正确理解更新功能现在使用固定时间步长但渲染没有帧速率限制?如果是这样,那正是我想要的。
    • 这正是它正在做的事情。
    【解决方案2】:

    我建议使用 setFrameRate 限制,因为它是在 SFML 中本地实现的,并且会更好地工作。 要获得经过的时间,您必须这样做:

    fpsElapsedTime = fpsTimer.getElapsedTime();
    

    如果我必须实现类似的东西,我会这样做:

    /* in the main loop */
    fpsElapsedTime = fpsTimer.getElapsedTime();
    if(fpsElapsedTime.asMillisecond() >= (1000/framerateLimit))
    {
       fpsTimer.restart();
      // All your content
    }
    

    其他的,用 sf::Color::White 或 sf::Color::Black 代替 (sf::Color(255,255,255))

    希望得到帮助:)

    【讨论】:

      猜你喜欢
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多