软件的设计应考虑到性能吗?

时间:2009-10-10 13:59:41

标签: language-agnostic oop design-principles

在考虑性能的情况下,是否建议将软件的组件或体系结构设计为零?我的意思是,在性能密集型环境中如何使用设计/架构?

在设计组件时,我们应该遵循良好的OO原则,并确保组件是“可扩展的”。这样我们在这里稍微调整一下设计,并在我们遇到性能问题时稍微调整一下。虽然这样,但我们经常会遇到性能问题,因为调整软件可能会有所帮助。

或者,如果我们想出一个设计,虽然很复杂,但会使性能问题变得轻而易举。我们仍然需要调整软件,但调整通常很简单,因为设计是面向性能的。

注意:在上面列出的两种情况中,我都试图在遇到性能问题之前调整软件的性能。要重新说出问题,软件的设计应该是以性能为导向的吗?

请不要回答我说这一切都取决于预期软件运行的环境。原因是任何工业级软件的客户似乎都想要越来越多的时间。您可能不会计划您的软件在性能密集型环境中持续运行,但如果必须,该怎么办?我们应该在感觉到时重新设计软件吗?

这个问题一周让我感到不安,我还没有答案。你对此有何看法?

10 个答案:

答案 0 :(得分:26)

当我写这篇文章时,有两个人已经回答了关于过早优化的Knuth引文。我认为这有点误导。关于这个问题背后的想法,以及关于这个主题的许多建议,在我看来,程序是算法的集合,如果它不够有效,我们可以确定哪些算法太慢并用某些东西取代它更好。

这种事情忽略了程序的相互关联性。这些算法都隐藏在一些API背后。虽然“愿景”是API背后的算法是不透明的并且可以与另一个算法互换,但它忽略了API对其调用者的约束。我已经完成了相当多的网络编程,并且通过设计无法有效工作的API很容易编写效率低下的软件,那么当你必须对全部使用的API进行基本修改时,你会怎么做? (在网络编程中,要求调用者在内存中构建完整消息的API比允许流式传输数据的API更容易设计和实现。)

所以,不要因简单而精辟的引语而堕落。你不应该为这些小东西而烦恼(特别是不要担心70年代人们所做的事情;编译器现在更加聪明)但完全忽视性能问题的态度“我们可以随时介绍和改进事情如果需要“可以让你走向死胡同,你必须做重大的重新实现。

哦,我也建议不要“为可扩展性而设计”。做最简单的事情,如果你后来发现你所拥有的东西的概括使事情变得更容易或更简单,那就去做吧。根据我的经验,进行不必要的通用设计只会导致难以使用的组件通常不是非常可扩展的,因为初始设计实际上无法预见组件在一般情况下应该做什么类型的事情以及如何。

答案 1 :(得分:5)

项目的设计必须平​​衡可扩展性,可维护性,性能,运输时间等。

我尝试设计包+高级图表以实现可扩展性,然后设计低级别的性能。

答案 2 :(得分:3)

我必须全心全意地回答jk的回答。

Knuth的引用在现实生活中有些不适用于一些不涉及架构的小问题领域

作为一个例子,我最近不得不花费3-4个月从头开始重新构建一个相当复杂的系统,因为最初的设计假设100%的数据将从数据库中加载到一个块中。在数据集增长到最初设计师预期的100倍之前,这种情况已经好了3年,并且系统开始在仅仅2G使用的内存不足或可怕的崩溃之间交替。

现在,解决方案在概念上很简单 - 允许批量检索数据。 这样聪明地工作。但是,在最初的设计阶段可能需要额外几周的工作,他们不得不考虑性能变成3个月的磨难,因为每个小功能,对象和API以及整体架构都明确写成假设“100%数据是“。

一般情况下,数据量是性能问题和数据分块的任何情况都是主要的可行解决方案,分块必须设计为前额

答案 3 :(得分:2)

我会说,只要你从一开始就不知道每一点点的表现都会很重要,那就选择好的面向对象原则。

通常通过算法优化而不是结构重构来实现大的性能提升(只要架构遵循正常的最佳实践)。选择更难以工作的设计所获得的性能提升通常与所有性能要求最高的环境无关,因此如果从一开始就不是绝对的顶级性能,那就选择优秀的OO。

答案 4 :(得分:2)

我想说,这就是经验丰富的软件工程师和软件新手的不同之处。

经验丰富的软件工程师应始终牢记其设计的性能问题。

示例:当您的模块内部具有O(n ^ 3)性能行为的算法可能会增加n时,可能会出现这样的情况:您的模块在某些情况下会变得非常慢。

当然,有很多不同之处。当你在内存数组中有O(n ^ 3)时,它可能在磁盘操作上作为O(n ^ 2)的问题较少。

因此,经验对于思考这些事情以及决定设计必须改变的位置或以后的调整可以使其更快而没有问题的地方非常重要。

答案 5 :(得分:1)

遵循OOP最佳实践的良好架构软件,广泛使用设计模式,或者原则上应该是可维护良好的。如今,低级优化很少有真正的作用,CPU和资源非常多。

只需代码可重用,可维护和可扩展。在这样一个良好的环境中,可以轻松实现对低级别优化的真正需求。只有在真正需要的时候,才会真正处理这个问题。

答案 6 :(得分:0)

您应始终以效率低于效率为目标,但不以牺牲可维护性为代价。所以,是的,您应该尝试设计效率,但要注意过早优化。 Donald Knuth最喜欢的一句话:

  

“我们应该忘记效率低下,大约97%的时间说:过早的优化是所有邪恶的根源。”

答案 7 :(得分:0)

几乎以“依赖”的方式,我认为你真的需要考虑你的要求是什么。如果最高优先级要求之一是“必须能够维持一些疯狂的吞吐量/性能水平”,那么你就不会在整体架构和技术选择中预先计划和设计。

答案 8 :(得分:0)

我觉得有趣的是只有Mikael Auno提到了“要求”这个词。

虽然Knuth的报价是 TRVTH ,但这一切都归结为要求。可伸缩性是其中之一吗?预期负荷是多少?如果你的答案是“我不知道”,问。

如果这些是要求,请在验收测试中添加负载测试。

您仍然希望设计可维护性。将性能考虑因素推迟到Last Responsible Moment,然后将配置文件 - 不要猜测。微优化是对公司资金的浪费。

有时负责的时刻很早就会发生;我不打算设计一个企业CRM系统,其中所有数据都作为XML文件存储在磁盘上。我要做的是抽象持久层。

最后Kolibri的评论是正确的 - 答案(像往常一样)是“它取决于。”

编辑:在重新阅读时,我担心我违反了OP的约束“请不要回答我说这一切都取决于预期软件运行的环境。”不过,我支持我的回答。如果(何时)需求发生变化,通常更容易修改简单设计。未说明的假设是我们提前知道要求将如何变更 。该请求可以是“使其按一个数量级进行扩展”或“允许在组织之间移动客户”。为前者构建可能会使后者更难实现。

答案 9 :(得分:0)

请勿提前进行任何优化。但体系结构会对系统的潜在性能产生巨大影响。

我建议使用以下书籍:Release It!: Design and Deploy Production-Ready Software