
一些优化需要复杂的数据结构和数千行代码。 在其他情况下,生产率的大幅提高只会带来最小的变化:有时您只需要将其设置为零即可。 这就像一个古老的
故事,关于一个船长 ,他知道用锤子敲打的正确位置,然后向客户收费:对阀门的打击为0.50美元,对击中位置的为999.50美元。
我个人遇到了一些性能错误,这些错误可以通过输入1零来解决的,在本文中,我想分享两个故事。
测量的重要性

在最初的Xbox时代,我帮助优化了许多游戏。 在其中之一中,探查器指向矩阵转换函数,该函数消耗了7%的CPU时间-图表上最大的飞跃。 因此,我努力着手优化此功能。

可以看出,我不是第一个尝试这样做的人。 该功能已在汇编器中重写。 我发现汇编语言有一些潜在的改进,并试图评估其效果。 这是重要的一步,否则很容易进行“优化”,这不会改变任何情况,甚至不会使情况恶化。
但是,测量很困难。 我运行了游戏,使用并行分析进行了一些测试,然后研究了配置文件:代码变得更快了。 似乎有所改善,但无法确定。
所以我运用了
科学的方法。 他编写了一系列测试来管理新旧版本的代码,以准确衡量性能差异。

这并没有花费太多时间:正如预期的那样,新代码比旧代码快约10%。
但是事实证明,10%的加速度是胡说八道。
有趣的是,测试代码内部的执行速度比游戏中快10倍。 这是一个令人兴奋的发现。
在检查了结果之后,我看了一会儿空白,但随后它突然出现在我身上。
缓存角色
为了使游戏开发人员具有完全的控制权和最佳性能,游戏机允许您分配具有各种属性的内存。 特别是,原始Xbox允许您分配不可缓存的内存。 将数据写入GPU时,这种类型的内存(实际上是页表中的标记类型)非常有用。 由于未缓存内存,因此写入将立即立即进入RAM,而不会出现任何延迟或“正常”映射导致缓存污染。
因此,非缓存内存是一项重要的优化,但应谨慎使用。 特别重要的是,游戏绝不要尝试从非缓存的内存中
读取内容 ,否则它们的性能将严重下降。 即使原始Xbox中相对较慢的
733 MHz CPU也需要其自己的缓存来提供足够的读取性能。
现在很清楚发生了什么。 显然,对于此功能,数据分配在非缓存的内存中,因此性能较低。 一次小型测试证实了这一假设,现在该解决问题了。 我找到了分配内存的行,双击标志值,并指向零。
该功能取代了约7%的处理器时间,而开始消耗了约0.7%的时间,不再成为问题。
在一周结束时,我的报告看起来像这样:“ 39,999小时的研究时间,0.001小时的编程时间是巨大的成功!”
开发人员通常无需担心意外分配非缓存内存:在大多数操作系统上,使用标准方法在用户空间中不可用此选项。 但是,如果您对有多少不可缓存的内存会降低程序速度感兴趣,请尝试使用
VirtualAlloc中的PAGE_NOCACHE或PAGE_WRITECOMBINE标志。
0 GiB优于4 GiB

我想告诉你另一个故事。 它与我发现的错误有关,其他人已修复它。 几年前,我注意到笔记本电脑上的磁盘缓存经常被清除。 我跟踪到达到4 GiB行时会发生这种情况,最后发现,当指向未知的扇区大小时,新备份HDD的驱动程序将SectorSize设置为0xFFFFFFFF(或-1)。 Windows内核将此值解释为4 GiB并分配相应的内存块,这引起了问题。
我在Western Digital中没有联系人,但可以放心地假设他们通过将常数0xFFFFFFFF(或-1)替换为零来解决了该错误。 一个字符输入-解决了一个严重的性能问题。
(在“慢速Windows:探索和识别”一文中阅读有关此研究的更多信息)观察结果
- 在两种情况下,问题都在于缓存
- 决定性的是使用探查器来查明问题。
- 如果未通过测量验证补丁,则不一定会有所帮助。
- 我可以写很多其他这样的案例,但是它们要么太秘密,要么太无聊。
- 正确的决定不必太复杂。 有时,巨大的改进会带来很小的变化。 您只需要知道在哪里
我碰巧通过取消注释#define和其他琐碎的更改来优化代码。 如果您有这样的故事,请在评论中告诉我们。