什么时候是考虑性能的最佳时间?


45

我来自软件开发背景。在软件开发周期中,我们通常专注于功能和工作产品。在开发结束时,我们开始优化代码并提高性能。

现在的问题是,我们是否需要考虑游戏开发中每行代码的性能?

这样做我觉得我们错过了设计模式和简洁的代码。我想知道游戏开发行业是否有最佳实践方法?


8
您可能会发现有关先前问题的有关过早优化的讨论很有用。
DMGregory

10
在一开始的时候。随着项目的进行,性能只会变差。
托马什Zato

10
您来自的软件开发背景听起来并不健康。设计必须在所有领域都考虑到性能因素。多少次网络往返,多少次数据库查询以及多少次使用的内存等等。您在哪个工程领域都无关紧要;如果您没有计划性能,则计划性能失败。
乔恩·瓦特

1
所有。的。时间。只需要一直做,就可以节省一些时间和无聊的任务,并且尝试进一步优化代码(如果有必要的话),将会发现自己在完成非常酷和令人讨厌的任务。那就是乐趣的开始。
Yates

6
“考虑”性能应在您决定制造具有用户产品的那一天发生。用户对性能的期望最低,如果不满足,则您的产品将失败。性能有成本,产品有预算。如果最低可接受性能的成本超过预算,则您的项目将失败。在第一天而不是第一天考虑这一点很明智。
埃里克·利珀特

Answers:


90

绩效工程

  • 遵循供应商的建议。
  • 使用正确的数据结构。
  • 实施正确的使用模式。
  • 不要做任何愚蠢的事情。

优化

  • 当已经编写的代码运行缓慢时,请对其进行度量,找出原因,并实现使其快速运行所需的条件。

过早优化

  • 对没有测量的快速或慢速进行假设,并将这些假设构建到代码的设计和编写方式中。

这三件事是不一样的

特别是性能工程是您从一开始就应该做的事情,并且它绝对与过早优化不同,因为它是基于实际测量的。在这种情况下,我们将根据经验和建议来了解硬件的工作方式以及快速或慢速的使用模式。

如果没有为性能而进行工程师设计,可能会导致糟糕的结果,就像在您发现任何错误时需要重新设计和重写一样。

例如:所有GPU供应商都建议每帧从GPU进行回读是缓慢的。设计代码不执行回读并不是过早的优化


28
非常感谢您提到这一点。开发人员总是用过分强调这一点的建议来传播过早优化的弊端,但是经验不足的开发人员通常不了解细微差别。从一开始就正确设计它。那不是过早的优化。我说你应该意识到自己写的每一行的表现。作为开发人员,您应该了解最佳做法,以免做蠢事。也就是说,您不应该因优化而陷入瘫痪。首先运行一些东西,然后专注于降低速度的东西。
AC AC

2
@AC我也想指出,好的设计可能要花一点时间才能开始,但是最后这可能意味着您也可以更快地完成工作,这意味着如果需要,可以花更多的时间进行优化。我的经验(用一个单独的,半完成的个人爱好项目来备份它)是,一旦您的项目足够大,那么大的时间就是1)“我将如何将其编织到已经存在的所有内容中”,以及2)“ Damnit,我一周前编写的代码非常适合,然后根本无法与我接下来要做的工作一起使用”。好的设计(我还没有做过)可以帮助这两个方面。
亚瑟

5
未能适当地为性能进行工程设计也可以认为是对设计的悲观。那么,如果过早的优化是万恶之源,那么过早的悲观化又是什么呢?; P
ninjalj

1
@Arthur“还有更多时间[剩余]进行优化”?这也是一种很好的观察方式,可以优化您自己有限的开发资源(和工作流程),以便从优化工作中获得最佳效果!另外,我知道我们的堆栈溢出不正确,但是令我惊讶的是我们在谈论优化,而帕累托原理还没有在答案中提及……我什至看不到“百分比”一词!
AC

1
在设计数据结构以实现良好性能时,您必须知道计算机可以有效地执行以及不能执行的操作。例如,现代CPU遍历数组可能会施加大量的蛮力,特别是如果您进行了设置,以便编译器可以使用SSE / AVX自动矢量化。(例如,使用x坐标数组和y坐标数组,而不是xy对结构或xyz三元组的数组。有关某些链接,请参见stackoverflow.com/tags/sse/info,尤其是Insomniac Games(GDC 2015)上的SIMD
Peter Cordes

22

如果您想在正确的时间进行优化,请使用慢速机器并使用它们。对于小型商店,一个不错的选择是在通勤时使用速度较慢的笔记本电脑,在办公室中使用快速桌面。另外一个好处是,如果您是一家专人商店,这也将迫使您正确备份整个构建环境。

通过使用速度较慢的计算机,您将知道何时需要提高性能。

我们是否需要考虑游戏开发中每行代码的性能?

绝对不。在任何类型的开发中,代码行的性能通常都是无关紧要的。您需要考虑算法和算法复杂性,而不是线条。在许多情况下,体面的编程意味着通过优化代码行可以使速度提高2倍左右,但是选择正确或错误的算法将导致数万至数百万的因素。

关于过早优化的讨论实际上并不是说优化不是一件坏事。这是因为人们未能优化正确的事物。您的时间是需要优化的变量之一,这可以通过不浪费时间来“优化”每30毫秒调用一次并执行100微秒的函数来实现。

换句话说:“加快”速度是没有意义的。您的目标是“足够快”。做出已经“足够快”的“更快”是浪费时间,而做出还不够“快”的“更快”只是意味着它仍然太慢。“更快”无关紧要,只有“足够快”才有意义。


1
算法只是解决方案的一半,正确使用数据结构也非常重要。另外,请提前计划可能的引入多线程和64位编译的功能-尽管并非在每种情况下都不需要这些功能,但有时这些功能确实很重要,而且如果没有计划的话,它们通常也不容易/便宜地适应。(我知道有些游戏同时遇到这两个问题。)
hoffmale

与Debug版本相比,Debug版本要慢得多。这意味着开发所需的机器比以可接受的速度运行游戏所需的机器快得多。
杰克·艾德利

高速缓存访​​问模式也很重要,并且可以相差10或100。例如,考虑一个朴素矩阵相乘(对于大矩阵)。在行主矩阵的一列上循环是可怕的。例如,对于在循环之前添加转置的相同算法复杂度,此Q&A的差异为13个性能差异,仅用于解决可怕的访问模式。(从优化的BLAS库中可以获得10或更多的系数,该系数甚至更关心缓存和SIMD ...)
Peter Cordes

9

不,您不必检查每一行,因为并非每一行都与性能相关。它主要取决于执行一行的频率。在游戏启动时执行一次需要花费1 ms的代码段是完全不相关的,值得一看的是在每帧执行时,如果一定要对每帧的每个游戏对象执行,则必须进行优化。

这也取决于您正在开发哪种游戏。当您开发具有图形强度的3D射击游戏时,与编写复古RPG游戏相比,您需要更加了解性能。

最后,最好的建议是测试,测试,测试。为您的游戏构建一些逼真的测试场景,这些场景会比实际游戏中预期的要多得多。在目标规格较低的硬件上进行测试。确保性能符合预期。当情况变得更糟时,请使用探查器查找瓶颈。


3

您需要付出足够的努力,至少要走下去“这可能会成为瓶颈,如果是的话,那么解决这个问题将涉及到什么变化呢?”。

一般而言,这需要在确定正确方向上花费的时间/资源与避免错误决策所花费的时间/资源之间取得平衡。

认为它有点像翻新公寓。有些决定可能会产生持久的影响(“哎呀,冰箱不再适合放在小柜子里了。”“哎呀,我想把我的浴室放水的地方”),但是您不会考虑油漆刷的每个行程如何可能会影响建筑物的结构稳定性。

或者,换句话说,不要将自己陷入困境。或者至少知道您何时将自己倒入一个角落,并确保这是您想回到的角落。例如:

  • 我是否将游戏更新率与图形帧率联系在一起?
  • 我要强制同步保存吗?
  • 我会强迫(非)确定性吗?

1

对于游戏,您的主要目标是在目标最低规格的计算机上达到目标帧速率(并可能达到最大加载时间等)。

为此,不,您不必担心每一行。

每当选择特定的策略,算法或容器时,您都必须尽早担心。如果您通过做出不充分的设计决策而使从根本上无法实现目标,那么以后可能进行的任何优化均无济于事。

接下来,您必须担心什么东西是并行的或可并行化的。游戏是大规模并行的,如果没有其他原因,那就是图形。
因此,并行不仅仅意味着“线程”,还包括图形API,磁盘访问或网络。每当您错过可以轻松地进行本机并行化的东西并行运行的机会时,例如由于同步不良(或完全不使用异步API),您将损失更多,无法通过其他方式进行优化。
你也不必担心,只要东西众所周知,它是瓶颈或停滞的根源,或是阻碍扩展的因素。例如,切换渲染状态,绘制调用,从GPU读回或打开文件。

最后,完成后,测试表明您符合目标帧速率,则需要进行优化。找到需要90%的时间的最大瓶颈,然后对其进行优化。如果这还不够,请找出最大的秒数。
如果您达到目标,那么恭喜您。继续前进,忘记它。


0

变得真实。答案是完全没有。没有讨论。

主要问题是您的询问方式:

我们是否需要考虑游戏开发中每行代码的性能?

您的意思是,在配置屏幕等方面?像一次性解析器一样,最大1kb的小配置文件?认真吗

大多数代码的时间紧迫性无关紧要。没有哪一种软件的每一条线都是时间紧迫的。无处。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.