我们的内存管理工具箱随着每一章的推进而不断丰富,现在知道了如何重载内存分配操作符(第7章),以及如何运用这项技能解决各种具体问题(第8章和第9章都给出了几个具有代表性的实际示例)。
人们想要掌控内存分配机制的一个重要原因是性能。如果断言击败库供应商所提供的这些函数的实现会很简单,那将是一个妄论(而且完全是错误的!),因为这些实现通常在平均情况下已经非常优秀,甚至可以说是非常出色。当然,前面这句话的关键之处在于“对于一般情况而言”。当使用场景具有事先已知的特殊性时,有时就可以利用这些信息,设计出一个性能可能大幅超越为平均性能优化的方案的实现。
本章讲述的是,如何利用对内存管理问题来构建一个表现优异的解决方案。这可能是一个平均速度更快的方案,一个即使在最坏情况下也足够快的方案,一个具有确定性执行时间的方案,或者一个能够减少内存碎片化的方案等。毕竟,在实际程序中存在许多不同的需求和限制条件,常常需要做出权衡和选择。
本章结束时,各位的工具箱将进一步扩展:
编写基于“内存池”(arena-based)的分配策略算法,以应对事先已知的约束条件
编写针对不同内存块大小的分配策略
理解这些技术所带来的好处及其相关风险
本章介绍的技术,将引导我们探索一些非常接近某些特定应用领域中,重载内存分配操作符的使用场景。因此,我们最初将把这些技术应用于一个“现实世界”的问题:在一个中世纪奇幻游戏中,兽人(Orcs)与精灵(Elves)之间的战斗。
由于在本章中会讨论优化技术(以及其他内容),因此有必要发出一些警告:优化是一件棘手的事情,就像一个不断变化的目标,今天让代码变快的方法,可能在明天反而会让它变慢。同样,理论上看起来是个好主意的优化,在实际实现和测试后可能会导致性能下降。有时候,可能花了很多时间优化一段不会被执行的代码,结果只是白白浪费了时间和资源。
在试图优化程序的某些部分之前,通常明智的做法是进行测量,理想情况下使用性能分析工具(profiling tool),以识别出那些真正可能从优化中受益的部分。然后,保留一个简单但正确的代码版本作为基准,并将其保存在手边。每次尝试进行优化时,都要将结果与基准代码进行比较,并定期运行这些测试,尤其是在更换硬件、库、编译器或版本时。
有时候,比如一次编译器升级可能会引入新的优化机制,它“看穿了”了原本简单的基准代码,使其比你精心设计的方案还要快。因此,请保持谦逊、理智,并在优化前尽早测量,且要经常测量。