【问题标题】:Analyzing function memory and CPU usage分析函数内存和 CPU 使用率
【发布时间】:2017-02-08 14:16:51
【问题描述】:

我正在制作一款电子游戏,它是一款非常小的 2D 射击游戏。最近我注意到当场景中有大约 9 个或更多子弹时,帧速率会急剧下降。我的笔记本电脑可以处理高级 3D 游戏,而且我的游戏非常简单,所以硬件应该不是问题。

所以现在我有一个非常大的代码(至少对于一个人来说),我很困惑我应该在哪里寻找?子弹相关的函数和类太多了,比如不知道怎么分析是渲染函数有问题还是更新函数有问题?其他程序我可以用MVS 2015的调试工具,但是对于一个游戏来说,就不太实用了,比如我在render函数前放了一个断点,一秒要检查60次加上我什么都不能输入所以我永远不会有子弹来测试渲染功能!我尝试使用任务管理器,发现每个子弹的 CPU 使用率上升得非常快,但是当游戏速度变慢时,只有 10% 的 CPU 被使用!

所以我的问题是:

  • 无法使用调试工具如何分析函数?

  • 为什么游戏仍然可以使用系统资源时速度变慢?

【问题讨论】:

  • 你需要做的是一些profiling。通过这种方式,您可以查看哪些函数花费的时间最多或被调用的次数最多,然后您可以开始查看它们以进行优化。虽然看起来你有一个好的开始,因为你知道它一定与“子弹”有关。

标签: c++ visual-studio debugging sfml


【解决方案1】:

要查看哪个部分消耗了大部分处理能力,您应该使用函数profiler。它不会“调试”,但它会在完成时创建一个报告。

Valgrind 是一个很好的工具。

为什么游戏变慢了?取决于您的实施。我可以创建一个程序,将两个数字相除,然后计算结果需要 5 分钟。

【讨论】:

  • Visual Studio 有自己的堆和 CPU 分析器,但它们可能在社区版本中不可用,我不确定。
  • @shayan 老实说,我还没有从书中学到这一点。我边做边学。试试看,边做边学。网上有很多教程。
  • @shayan 我理解,但具有讽刺意味的是,我的回答仍然适用。想想sleep 命令。这完全取决于您的实施。你永远不会找到这个问题的唯一答案。
  • @Shayan 老实说,好的代码确实是一个视角问题,你的书可能声称是关于编写好的代码,但这并不意味着它是一本关于如何编写好的代码的好书。关于您关于为什么不使用更多 CPU 资源的帖子,您是否将其开发为多线程?程序不会自动检测有多少可用 CPU 资源,只会从中获取资源,除非您开发游戏来做到这一点。
  • @Shayan 很多这些高级 3D 游戏都利用了一些功能,例如将工作卸载到其 GPU 上,使用诸如计算着色器之类的东西,甚至进行自己的负载平衡在您的 CPU 上,为了让它们占用资源,这些功能不仅是程序附带的,而且必须开发到应用程序中。
【解决方案2】:

我们也从事视频游戏行业,我们在 PC 上使用一个非常简单的工具进行 CPU 分析:非常困。

http://www.codersnotes.com/sleepy/

这很简单,但确实帮助了我很多次。只需从 IDE 启动程序,让非常困倦的运行几千个样本,然后就可以开始了!

【讨论】:

  • 你能详细解释一下吗?该网站并没有真正描述它是如何工作的。排他性和包容性是什么意思?
  • Inclusive 是包括对子例程的所有潜在调用在内的时间。排他性是仅在该例程中花费的时间。例如,update 例程可能会花费 50% 的帧时间,包括在内,但例程本身很可能包含对不同例程的一些调用。如此独特,它可能只有几个 %。
  • 我对游戏进行了测试,有 3 个函数占用 CPU 资源最多。 79% Exclusive 的 RtlSubscribeWnfStateChangeNotification 位于顶部。我写的最消耗CPU的函数只消耗0.02% Exclusive...这给了我什么线索?
  • 您需要弄清楚RtlSubscribeWnfStateChangeNotification 是什么以及为什么它会耗费这么多时间。首先要找到该函数的调用堆栈。它必须在您的代码中的某处调用。尝试找到它,看看到底发生了什么。
【解决方案3】:

说到内存漏洞,Valgrind 是一个很好的工具,正如 The Quantum Physicist 已经指出的那样。 对于时间安排,我会编写自己的小型跟踪/分析工具(如果我的 IDE 还没有的话)。使用文本调试输出将短消息写入日志文件。类似的东西:

void HandleBullet() {
    printf("HandleBullet START: %i", GetSysTime());
    // do your function stuff
    printf("HandleBullet END: %i", GetSysTime()); // or calculate time of function directly
}

在您认为可能需要很长时间的所有函数中写入这些调试消息。 执行一段时间后,您可以查看该文件并查看是否发生了明显的事情(在某处阻塞)。 如果没有,请使用您选择的高级语言为您创建的日志文件编写一个小型解析器,以整理和分析您的输出。计算诸如在某个函数上花费的总时间之类的东西,或者绘制哪些函数花费时间最长的图表。如果您坚持使用易于解析的日志消息样式,应该不会太难。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-07
    • 2011-09-11
    • 2022-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多