计算机科学和编程中最常见的咒语之一是永远不要过早地进行优化,这意味着在发现问题之前不应优化任何内容,因为代码可读性/可维护性可能会受到影响。
然而,有时您可能知道某种特定的做事方式会表现不佳。在确定问题之前何时可以优化?从一开始就允许哪种优化?
例如,使用尽可能少的数据库连接,并在开发过程中密切关注它,而不是根据需要使用新连接并担心以后的性能成本
答案 0 :(得分:26)
我认为你错过了那个格言。从一开始就以最有效的方式做某事是没有错的,提供它也很明确,直接等等。
关键是你不应该把自己(更糟糕的是,你的代码)绑在一起试图解决可能根本不存在的问题。保存这种极端优化级别,这些优化通常在开发,维护,技术债务,错误滋生,可移植性等方面成本很高,适用于真正需要它的情况。
答案 1 :(得分:14)
我认为你正在以错误的方式看待这个问题。避免过早优化的目的不是为了避免优化,而是为了避免你可能陷入的心态。
以最清晰的方式编写算法。然后确保它是正确的。然后(并且只有那时)担心性能。但也要考虑维护等。
如果您遵循这种方法,那么您的问题就会自行解决。从一开始就允许的唯一“优化”是至少与直接方法一样清晰的那些。
答案 2 :(得分:6)
您可以在任何时间进行的最佳优化是为问题选择正确的算法。令人惊讶的是,一个小小的想法经常产生一个更好的方法,可以节省数量级,而不是几个百分点。这是一场彻底的胜利。
要寻找的东西:
答案 3 :(得分:4)
答案 4 :(得分:4)
来自维基百科:
我们应该忘记小事 效率,约占97% 时间:过早优化是 万恶之源。但我们不应该 放弃我们的机会 至关重要3%。 - 唐纳德克努特
我认为这总结了一下。问题是知道你是否在3%以及采取什么途径。我个人忽略了大多数优化,直到我至少让我的代码工作。通常作为一个单独的通道与分析器,所以我可以确保我正在优化实际重要的事情。通常情况下,代码运行得足够快,以至于您所做的任何事情都会产生很小的影响。
答案 5 :(得分:3)
如果您没有性能问题,那么您不应该牺牲性能的可读性。但是,在选择实现某些功能的方法时,从性能的角度来看,应该避免使用您知道存在问题的代码。因此,如果有两种方法可以实现一个功能,那么选择一个可能表现更好的方法,但如果它不是最直观的解决方案,请确保你为什么用这样的方式编写了一些注释。
答案 6 :(得分:2)
随着您作为开发人员的职业发展,您将逐渐意识到更好,更合理的方法来解决各种问题。在大多数情况下,我可以想到, 性能增强工作导致代码实际上比通过解决问题而演变的一些复杂纠结更小更简单。随着您的进步,这种更简单,更快速的解决方案变得更容易,更自然。
更新:到目前为止,我在线程上为每个人投票+1,因为答案非常好。特别是,DWC通过一些很好的例子抓住了我的立场的本质。
答案 7 :(得分:2)
<强>文档强>
记录您的代码是(开发过程中)的第一优化,您可以从一开始就做到这一点。随着项目的发展,与您互动的人越多,理解您所写内容的人越多,您花费的时间就越多
<强>工具箱强>
确保您的工具包适合您正在开发的应用程序。如果您正在制作一个小应用程序,则没有理由调用基于Eclipse的GUI系统的强大功能。
<强> Complilers 强>
让编译器完成艰难的工作。大多数情况下,编译器上的优化开关将完成您需要的大部分重要事项。
系统特定优化
特别是在嵌入式领域,了解您正在与之交互的CPU和系统的底层架构。例如,在Coldfire CPU上,通过确保数据位于正确的字节边界,可以获得大幅度的性能提升。
<强>算法强>
努力使访问算法O(1)或O(Log N)。努力使列表上的迭代不超过O(N)。如果您正在处理大量数据,如果可能的话,请避免超过O(N ^ 2)。
代码技巧
尽可能避免。这本身就是一种优化 - 一种优化,可以使您的应用程序在长期内更易于维护。
答案 8 :(得分:1)
如果您认为优化的代码速度很慢,那么您应该避免所有优化。您应该优化的唯一代码是当您知道它很慢时(最好是通过分析器)。
如果您编写清晰,易于理解的代码,则可能性足够快,如果不是,那么当您加快速度时,应该更容易做到。
话虽如此,常识应该适用(!)。你应该反复阅读文件还是应该缓存结果?可能会缓存结果。因此,从高级架构的角度来看,您应该考虑优化。
优化的“邪恶”部分是以更快的速度提交的“罪” - 这些罪通常导致代码很难理解。我不是100%肯定这就是其中之一..但在this question here,这可能是也可能不是最优化的例子看(可以是个人认为做到这一点),但也有比较明显的解决问题的方法比选择的方法要多。
我能做的另一件事,就是我最近做过的事情,就是在你编写代码的时候,你需要决定如何做一些事情来编写它并通过一个分析器来运行它。然后选择最清晰的方式来编码它,除非速度/内存有很大差异(取决于你所追求的)。这样你就不会猜测什么是“更好”,你可以记录为什么你这样做,以便有人不会在以后改变它。
我正在做的情况是使用内存映射文件-vs-流I / O ...内存映射文件明显比其他方式快,所以我不担心代码是否更难遵循(事实并非如此,因为加速很快。
我遇到的另一个案例是决定用Java“实习”字符串。这样做可以节省空间,但需要花费时间。在我的情况下,节省的空间并不大,而且时间是两倍,所以我没有进行实习。记录它可以让其他人知道不要打扰实习(或者如果他们想看看Java的新版本是否能让它更快,那么他们可以尝试)。
答案 9 :(得分:1)
除了清晰明了之外,您还必须花费合理的时间来正确实现代码。如果你花了一天的时间让代码正常工作,而不是你刚写完它就会花费两个小时,那么你很可能浪费时间来修复真实性能问题(Knuth的3%)。
答案 10 :(得分:0)
在这里同意Neil's opinion,立即对代码进行性能优化是一个糟糕的开发实践。
恕我直言,性能优化取决于您的系统设计。如果您的系统设计不佳,从性能的角度来看,没有多少代码优化会让您获得“良好”的性能 - 您可能会获得相对更好的性能,但性能不佳。
例如,如果一个人打算构建一个访问数据库的应用程序,一个设计良好的数据模型,如果可能产生比其相反的更好的性能特征,那么它已经被非规范化了 - 一个设计不良的数据模型已经过优化/调整以获得相对更好的性能。
当然,我们不能忘记这种混合中的要求。在设计过程中必须考虑隐含的性能要求 - 设计面向公众的网站通常需要减少服务器端访问以确保最终用户的“高性能”感觉。这并不意味着你在浏览器上重建每个动作的DOM并重新绘制它(我已经在实际中看到了这一点),但是你重建了DOM的一部分并让浏览器完成其余的操作(这将会有由理解隐含要求的合理设计师处理。
答案 11 :(得分:0)
选择适当的数据结构。我甚至不确定它是否算优化,但它会影响应用程序的结构(因此很早就可以做到)并大大提高性能。
答案 12 :(得分:-2)
如果您确定将在每次传递时计算此值,请不要直接在循环检查表达式中调用Collection.ElementCount。
而不是:
for (int i = 0; i < myArray.Count; ++i)
{
// Do something
}
执行:
int elementCount = myArray.Count;
for (int i = 0; i < elementCount ; ++i)
{
// Do something
}
经典案例。
当然,你必须知道它是什么类型的集合(实际上,如何实现Count属性/方法)。可能不一定很省钱。