好的代码顺序应该是干净,健壮和快速的。
Image Credits: Unsplash.com Harley Davidson
我的第一个“快速完成此代码”(技术上的代码优化)分配是一个庞大的SAP定制应用程序,具有30,000多行代码。
该应用程序加载数据的速度非常慢,显然,用户对此并不满意。
我必须承认,应用程序写得很好。 最佳地进行了数据库调用。 仅根据需要使用循环,并且在应用程序中充分考虑了模块性。 有两天时间,我在应用程序上大汗淋漓,进行了各种测试并检查了代码逻辑,但找不到任何使应用程序变慢的东西。
我脑力耗尽。 我没有其他选择了。 然后,在第三天,我发现了问题。
这是其中一个加载页面中的Wait语句-
WAIT FOR 20 SECONDS.
在过去的调试过程中,似乎有些开发人员插入了一个wait语句,却忘记了将其移至生产环境之前将其删除。 在标准代码中已从出口处调用它,进一步放大了问题。 我删除了该声明。 答对了!!! 它开始工作了。
也就是说,代码优化是一把双刃剑。
优化软件是一件好事,但这并不是可以保证的。
如果针对错误的事物或以错误的方式对软件进行优化,则优化会增加成本,减慢生产速度,并实际上使软件达到最佳效果。
在大多数情况下,都需要进行认真的权衡。 例如,提高速度可能会浪费您的资源利用率,而轻松地更有效地利用存储会降低速度。 您需要仔细考虑您愿意在其他领域进行哪些权衡,以实现您的主要目标。
您可以考虑以下几点指示,以使您的代码更具响应性,并减少您对客户端设备及其连接的数据库造成的压力。
不要做优化
优化的首要原则是“不要做”。
该程序已经足够好了吗? 知道该程序将如何使用以及它在其中运行的环境,使其更快会有什么好处? 这些是在优化代码之前应该问的一些问题。
是。 仅当程序很重要且确实很慢时,才需要付出努力并降低成本,然后才能保持稳定,正确性和清晰度,并且可以更快地进行优化。
一个快速获得错误结果的程序对任何人都没有用。 有效优化的软件利多于弊,但是,如果您错误地进行了优化,则情况恰恰相反。
因此,第一件事就是设定优化目标。
您需要首先清楚地了解您要完成的任务以及各种优化与这些目标的关系。 需要清晰,简单地陈述这个目标-足够简单,以至于最不懂技术的部门经理可以理解和阐明它-并且您需要在整个过程中坚持这些目标。
最好的开始方法是根据对目标的影响来确定要进行的工作的优先级。 无论您在做什么,都应该可以衡量。 直觉永远是一个非常糟糕的指南。
使用Profiler
在进行任何分析之前,请先对其进行概要分析。 最常见的性能调整错误是花一天时间重写代码,而这些代码只消耗了总运行时间的一小部分。
概要文件是程序花费时间的度量。 一些配置文件列出了每个函数被调用的次数,以及所消耗的执行时间。
其他的则显示每个语句执行了多少次。 经常执行的语句对运行时间的贡献更大,而从未执行的语句可能表示无用的代码或未经正确测试的代码。
一个好的性能分析工具的最大优点是可以找到程序中的热点,占用大部分计算时间的函数或代码段。 在大多数情况下,找到热点都会发现问题。
使用概要分析的最佳方法是识别热点,将其改进到可能的程度,然后再次进行测量以查看是否出现了新的热点。
启用编译器优化
通常,一种肯定的优化方法是打开编译器提供的内置优化。
编译器优化通常可以将运行时间优化从几个百分点到2倍。有时它可能还会减慢产品速度,因此在进行最终调用之前请仔细测量。 但是,现代编译器在这方面做得很好,因为它们避免了程序员对小规模更改的大量需求。
而且一些现代的编译器还具有全局优化器,可以分析整个程序以获得潜在的改进。 如果您的系统中提供了这样的编译器,请一定尝试一下。 可能会减少几秒钟。
关键是,编译器进行的优化越积极,就越有可能在已编译的程序中引入错误。 因此,始终建议在启用编译器优化后重新运行回归测试,以防止出现任何意外情况。
调整代码
一旦发现热点,我们可以使用多种技术来调整代码。 但是,考虑到编译器可能正在为您做很多事情,并且您的努力可能会使程序进一步复杂化,因此应谨慎使用。 无论您尝试什么,请确保在继续操作之前先评估其影响。 这里有一些调优建议。
收集常见的子表达式。
如果在多个地方进行昂贵的计算,最好在一个地方进行计算并记住结果。 除非需要,否则不要将此类计算放在一个循环中。
用廉价的操作代替昂贵的操作。
字符串操作可能是任何程序中最常见的操作之一。 但是,如果操作不正确,则操作可能会很昂贵。 同样,在某些情况下,可以通过用一系列移位运算代替乘法来提高性能。 即使这是有效的(但并非总是如此),它也会产生令人困惑的代码。 因此,还要考虑代码的可读性来做出决定。
消除循环。
循环主要是开销。 如果迭代次数不多,请尽量避免循环。
缓存常用值。
缓存利用了局部性,程序和人们重用最近使用的数据的趋势。 仅缓存最常用的字符或数据可大大提高程序的性能。
用较低级别的语言重写。
这应该是最后的手段。 尽管从程序员的角度来看,较低级的语言会消耗更多开发时间,但较低级的语言往往会更有效。 有时,通过用低级语言重写关键代码会获得重大改进,但这是以降低可移植性为代价的,并且维护变得非常困难。 因此,请谨慎做出决定。
请记住,在优化中,选择可能是游戏的90%。 值得花时间来决定自己的工作,并正确地做。 当然:这也是黑魔法所在!
最后,将代码检查纳入治理模型
这既适用于管理人员,也适用于开发人员。 经理应确保将代码检查作为项目检查的一部分,而开发人员应将其作为最佳编码实践的一部分。
低效的代码不会对系统的日常运行造成太大影响。 由于存在这一明显的缺陷,我们倾向于忽略效率低下的代码,因为它并没有真正伤害到任何人,对吗? 不对! 随着时间的流逝,代码效率低下,这会导致执行速度变慢,并且客户端的处理时间过长。
从长远来看,应该结合常规代码检查来删除效率低下的代码片段,尽管除非您将无效的代码留在那里,并且稍后不得不怀疑为什么您的代码要花这么长的时间,否则您可能会不满意它的执行时间。 不要让过去成为你未来的痛苦。 尽可能检查代码的效率。
让别人对您的工作进行代码审查。 理想情况下,此人是您欣赏的开发人员,但几乎所有开发人员都可以。 如果有人听/看不懂您的部分代码,那就是一个危险信号。
记住改进任何代码都是从您开始。 从第一遍开始就没有办法完美地编码所有东西。 总是需要对代码进行更改,要解决错误,有时您的代码无法按照您想要的方式工作。 很好,这完全是成为一名程序员的一部分。
在大多数情况下,它所需要的只是对代码进行一些清理,以使其像jalopy一样停止工作,而像经过微调的布加迪一样开始工作。 使清洁代码成为一种习惯,就是这样!!!
正如肯特·贝克说的那样。
“我不是一个伟大的程序员; 我只是一个有良好习惯的优秀程序员。”
·编程实践— Rob Pike。
·清洁代码-罗伯特·马丁(Robert Martin)。
·编程珍珠-乔恩·本特利
·内循环-Rick Booth
·敏捷开发人员的实践— Andy Hunt
(本文翻译自Ravi Shankar Rajan的文章《5 Powerful Ways to Make Your Code Run Faster.》 参考https://medium.com/swlh/5-powerful-ways-to-make-your-code-run-faster-b99ef1e20626)