在这个网站上已经有很多性能问题了,但是在我看来,几乎所有的问题都是非常具体的,而且相当狭窄。几乎所有人都重复了避免过早优化的建议。

我们假设:

代码已经正常工作了 所选择的算法对于问题的环境已经是最优的 对代码进行了测量,并隔离了有问题的例程 所有优化的尝试也将被衡量,以确保它们不会使事情变得更糟

我在这里寻找的是策略和技巧,在一个关键算法中,当没有其他事情可做,但无论如何都要挤出最后百分之几。

理想情况下,尽量让答案与语言无关,并在适用的情况下指出所建议的策略的任何缺点。

我将添加一个带有我自己最初建议的回复,并期待Stack Overflow社区能想到的任何其他东西。


当前回答

调整操作系统和框架。

这听起来可能有点夸张,但可以这样想:操作系统和框架被设计用来做很多事情。您的应用程序只做非常具体的事情。如果你能让操作系统完全满足你的应用程序的需求,并让你的应用程序理解框架(php,.net,java)是如何工作的,你就能从硬件上得到更好的东西。

例如,Facebook改变了Linux中的一些内核级别的东西,改变了memcached的工作方式(例如,他们写了一个memcached代理,使用udp而不是tcp)。

另一个例子是Window2008。Win2K8有一个版本,你可以安装运行X应用程序所需的基本操作系统(例如web应用程序,服务器应用程序)。这大大减少了操作系统在运行进程方面的开销,并为您提供了更好的性能。

当然,你应该在第一步就投入更多的硬件……

其他回答

不好说。这取决于代码的样子。如果我们可以假设代码已经存在,那么我们可以简单地查看它并从中找出如何优化它。

更好的缓存位置,循环展开,尽量消除长依赖链,以获得更好的指令级并行性。尽可能选择有条件的移动而不是分支。尽可能利用SIMD指令。

理解你的代码在做什么,理解它运行在什么硬件上。然后,决定需要做什么来提高代码的性能就变得相当简单了。这是我能想到的唯一一个真正具有普遍性的建议。

好吧,还有“在SO上显示代码,并为特定的代码段寻求优化建议”。

不可能有这样的全面陈述,这取决于问题领域。一些可能性:

因为你没有直接指定你的应用程序是100%计算:

搜索阻塞的调用(数据库,网络硬盘,显示更新),并隔离它们和/或将它们放入线程中。

如果你使用的数据库恰好是Microsoft SQL Server:

研究nolock和rowlock指令。(在这个论坛上有一些讨论。)

如果你的应用是纯粹的计算,你可以看看我关于旋转大图像缓存优化的问题。速度的提高使我大吃一惊。

这是一个长期的尝试,但它可能提供了一个想法,特别是如果您的问题是在成像领域:代码中旋转位图

另一个是尽量避免动态内存分配。一次分配多个结构,一次释放它们。

否则,请确定最紧密的循环,并将它们与一些数据结构一起张贴在这里(无论是伪的还是非的)。

更多的建议:

Avoid I/O: Any I/O (disk, network, ports, etc.) is always going to be far slower than any code that is performing calculations, so get rid of any I/O that you do not strictly need. Move I/O up-front: Load up all the data you are going to need for a calculation up-front, so that you do not have repeated I/O waits within the core of a critical algorithm (and maybe as a result repeated disk seeks, when loading all the data in one hit may avoid seeking). Delay I/O: Do not write out your results until the calculation is over, store them in a data structure and then dump that out in one go at the end when the hard work is done. Threaded I/O: For those daring enough, combine 'I/O up-front' or 'Delay I/O' with the actual calculation by moving the loading into a parallel thread, so that while you are loading more data you can work on a calculation on the data you already have, or while you calculate the next batch of data you can simultaneously write out the results from the last batch.

建议:

Pre-compute rather than re-calculate: any loops or repeated calls that contain calculations that have a relatively limited range of inputs, consider making a lookup (array or dictionary) that contains the result of that calculation for all values in the valid range of inputs. Then use a simple lookup inside the algorithm instead. Down-sides: if few of the pre-computed values are actually used this may make matters worse, also the lookup may take significant memory. Don't use library methods: most libraries need to be written to operate correctly under a broad range of scenarios, and perform null checks on parameters, etc. By re-implementing a method you may be able to strip out a lot of logic that does not apply in the exact circumstance you are using it. Down-sides: writing additional code means more surface area for bugs. Do use library methods: to contradict myself, language libraries get written by people that are a lot smarter than you or me; odds are they did it better and faster. Do not implement it yourself unless you can actually make it faster (i.e.: always measure!) Cheat: in some cases although an exact calculation may exist for your problem, you may not need 'exact', sometimes an approximation may be 'good enough' and a lot faster in the deal. Ask yourself, does it really matter if the answer is out by 1%? 5%? even 10%? Down-sides: Well... the answer won't be exact.

不像之前的答案那么深入或复杂,但下面是: (这些更多是初级/中级水平)

明显:干 向后运行循环,所以总是与0比较,而不是与变量比较 尽可能使用位操作符 将重复的代码分解为模块/函数 缓存对象 局部变量具有轻微的性能优势 尽可能限制字符串操作