Herb Sutter 的C++ 编码标准说要避免Premature optimization
和Premature pessimization
. 但我觉得两者都在做同样的事情。因此,期待一些帮助来澄清这两个概念以及它们之间的区别。如果你想出一些例子,对其他人会更有好处。
这是一个很好的解释Premature optimization
。但我找不到任何Premature pessimization
5 回答
我认为,他所说的过早悲观化与过早优化正好相反:根本无视使用哪种数据结构和算法。
过早的优化通常涉及算法的微小细节,这些细节可以稍后进行调整,并且不需要在开始时关注。
相比之下,过早的悲观化涉及代码架构的高级设计:例如,您的库的一个根本上低效的接口不能在以后通过优化来修复,因为公共接口几乎是一成不变的。
Herb 的意思是当你面对两个同样可读的选项时,总是选择最有效的一个。
使用std::vector::reserve()
或最好的标准容器或算法并不是过早的优化。然而,不使用它们将是过早的悲观。
过早的优化是指您为了某些甚至可能不值得的“优化”而牺牲可读性。为此使用探查器。
编程时有小规模和大规模的选择。
悲观化是指以“阻止编译器做好工作”的方式编写代码。一个典型的例子是,当函数非常小且简单(例如 {s,g}etter)时,不要将函数放置在允许它们内联的位置。这可以使函数花费它应该花费的时间的 10 倍,并且“正确”是一件如此简单的事情。
我在这个网站上发现几次的悲观情绪是使用“a /= 2;” 当 "a >>= 1" 同样合适时。如果我们知道这a
不是负数,那么左移和除法具有相同的效果,但即使编译器优化除法,它几乎总是会产生更多代码来应对“它可能是负数”的情况 - 额外的代码可以在某些情况下会成为真正的性能打击。
过早的优化是当您展开循环或以其他方式使代码更复杂时,仅仅是因为您不相信编译器会做好 - 通常没有证据表明它不会做好。
另一个示例是“不使用std::vector
”,而是您自己的expandable array
,因为“向量太慢”,甚至没有使用std::vector
.
我倾向于认为过早悲观化只是对导致过早优化的性能要求的误解。即您错误地认为您的代码执行速度不够快或使用太多资源(悲观主义),因此您在不需要的地方进行优化。
随着越来越多的大型数据集的出现,我倾向于看到更频繁的反转,即缺乏足够的悲观情绪导致选择无法扩展以满足用户需求的算法。这通常与编译器优化可以替代糟糕的算法选择的信念相结合。
在传递引用合适时定义传递值参数
是避免过早悲观的最简单的例子之一。它没有任何成本,只是成为第二天性,并且可以为您节省一些性能缺陷。
假设您指的是这本书 - C++ Coding Standards: 101 Rules, Guidelines, and Best Practices。2004 年 10 月 ISBN:0321113586 - 项目 9 和 25 给出了几个例子:
- 不要过早地悲观
- 通过值、(智能)指针或引用适当地获取参数