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

我们假设:

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

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

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

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


当前回答

减少可变大小(在嵌入式系统中)

如果您的变量大小大于特定体系结构上的单词大小,则会对代码大小和速度产生重大影响。例如,如果你有一个16位系统,经常使用一个长int变量,然后意识到它永远不能超出范围(−32.768…32.767)考虑将其减少到短int。

从我的个人经验来看,如果一个程序已经准备好或几乎准备好了,但是我们意识到它占用了目标硬件程序内存的110%或120%,那么对变量进行快速归一化通常可以解决这个问题。

到这个时候,优化算法或部分代码本身可能会变得令人沮丧的徒劳:

重新组织整个结构,程序就不再像预期的那样工作,或者至少引入了许多错误。 做一些聪明的技巧:通常你花了很多时间优化一些东西,并发现代码大小没有或很小的减少,因为编译器无论如何都会优化它。

Many people make the mistake of having variables which exactly store the numerical value of a unit they use the variable for: for example, their variable time stores the exact number of milliseconds, even if only time steps of say 50 ms are relevant. Maybe if your variable represented 50 ms for each increment of one, you would be able to fit into a variable smaller or equal to the word size. On an 8 bit system, for example, even a simple addition of two 32-bit variables generates a fair amount of code, especially if you are low on registers, while 8 bit additions are both small and fast.

其他回答

缓存!要使几乎任何事情都变得更快,一个便宜的方法(在程序员的努力中)是在程序的任何数据移动区域添加缓存抽象层。无论是I/O还是只是传递/创建对象或结构。通常,向工厂类和读取器/写入器添加缓存是很容易的。

有时缓存不会给你带来太多好处,但这是一种简单的方法,只需添加缓存,然后在没有帮助的地方禁用它。我经常发现这样做可以获得巨大的性能,而无需对代码进行微观分析。

由于许多性能问题都涉及数据库问题,因此在调优查询和存储过程时,我将介绍一些需要注意的具体问题。

避免在大多数数据库中使用游标。也要避免循环。大多数时候,数据访问应该基于设置,而不是逐条记录处理。这包括当您希望一次插入1,000,000条记录时,不要重用单个记录存储过程。

不要使用select *,只返回实际需要的字段。如果存在任何连接,则尤其如此,因为连接字段将重复,从而在服务器和网络上造成不必要的负载。

避免使用相关的子查询。使用连接(尽可能包括到派生表的连接)(我知道这对于Microsoft SQL Server是正确的,但是在使用不同的后端时测试建议)。

索引,索引,索引。如果适用于您的数据库,请更新这些统计数据。

使查询sargable。这意味着避免一些不可能使用索引的事情,例如在like子句的第一个字符中使用通配符,或在join中的函数中使用通配符,或作为where语句的左侧部分。

使用正确的数据类型。在日期字段上进行日期计算要比尝试将字符串数据类型转换为日期数据类型然后进行计算快得多。

永远不要在触发器中放入任何形式的循环!

大多数数据库都有一种方法来检查如何执行查询。在Microsoft SQL Server中,这被称为执行计划。先检查一下,看看问题出在哪里。

在确定需要优化的内容时,考虑查询运行的频率以及运行所需的时间。有时,对一个每天运行数百万次的查询稍作调整,可以获得比删除一个月只运行一次的long_running查询更多的性能。

使用某种分析器工具来找出发送到数据库和从数据库发送的内容。我记得过去有一次,我们不知道为什么页面加载这么慢,而存储过程却很快,并通过分析发现网页多次而不是一次地请求查询。

剖析器还将帮助您找到谁在阻止谁。一些单独运行时执行很快的查询可能会因为来自其他查询的锁而变得非常慢。

你在什么硬件上运行?您是否可以使用特定于平台化的优化(如向量化)? 你能找到更好的编译器吗?比如从GCC换成Intel? 你能让你的算法并行运行吗? 可以通过重新组织数据来减少缓存丢失吗? 可以禁用断言吗? 对编译器和平台进行微优化。在if/else语句中,把最常见的语句放在前面

以下是我使用的一些快速而粗糙的优化技术。我认为这是“第一关”优化。

了解时间都花在了什么地方。是文件IO吗?是CPU时间吗?是因为网络吗?是数据库吗?如果IO不是瓶颈,优化IO是没有用的。

了解您的环境了解在哪里进行优化通常取决于开发环境。例如,在VB6中,通过引用传递比通过值传递慢,但是在C和c++中,通过引用传递要快得多。在C语言中,如果返回代码表明失败,尝试一些东西并做一些不同的事情是合理的,而在Dot Net中,捕获异常比尝试前检查有效条件要慢得多。

在频繁查询的数据库字段上构建索引。你几乎总是可以用空间来换取速度。

在要优化的循环内部,我避免了必须进行任何查找。找到循环外的偏移量和/或索引,并重用循环内的数据。

最小化IO尝试以一种减少必须读或写的次数的方式进行设计,特别是在网络连接上

减少抽象代码必须通过的抽象层越多,它就越慢。在关键循环内部,减少抽象(例如,揭示避免额外代码的低级方法)

对于带有用户界面的项目,生成一个新线程来执行较慢的任务使应用程序感觉反应更快,尽管不是。

你通常可以用空间来换取速度。如果有计算或其他密集的操作,看看是否可以在进入关键循环之前预先计算一些信息。

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

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