我有一个Delphi 2009程序,它处理大量数据,需要尽可能快,不要使用太多内存.
您通过显着减少执行时间或内存使用对Delphi代码进行了哪些小的简单更改,这些更改对程序的性能影响最大?
谢谢大家的所有答案.很多很棒的提示.
为了完整起见,我将发布一些关于Delphi优化的重要文章.
在开始在About.com上优化Delphi代码之前
速度和大小: About.com 上的十大技巧
高性能Delphi中的代码优化基础和Delphi优化指南,与Delphi 7相关但仍然非常相关.
.BeginUpdate;
.EndUpdate;
;)
使用Delphi Profiling工具(有些人在这里或这里)并发现你自己的瓶颈.优化错误的瓶颈是浪费时间.换句话说,如果你在这里应用所有这些建议,但忽略了某些人在一些非常重要的代码中放置睡眠(1000)(或类似)的事实是浪费你的时间. 首先修复您的实际瓶颈.
停止使用TStringList处理所有事情.
TStringList 不是一个通用的数据结构,用于有效存储和处理从简单到复杂类型的所有内容.寻找替代品.我使用Delphi容器和算法库(DeCAL,以前称为SDL).Julians EZDSL也应该是一个不错的选择.
预分配列表和数组,而不是在每次迭代时增长它们.
就速度而言,这可能对我产生了最大的影响.
如果需要在循环中使用Application.processmesssages(或类似),请尝试仅在每第N次迭代时调用它.
同样,如果更新进度条,请不要每次迭代都更新它.相反,每x次迭代将其增加x个单位,或者根据时间或总任务长度的百分比来缩放更新.
FastMM
FastCode(lib)
使用高性能数据结构,如哈希表(等).很多地方制作一个循环可以更快地为您的数据创建查找哈希表.使用相当多的内存,但肯定是快速的.(这可能是最重要的一个,但首先是简单的2,需要很少的努力)
减少磁盘操作.如果有足够的内存,则将文件完全加载到RAM并在内存中执行所有操作.
考虑仔细使用线程.如果您现在不使用线程,请考虑添加一对.如果你是,请确保你没有使用太多.如果您在双核或四核计算机上运行(大多数都是如此),那么正确的线程调整非常重要.
您可以查看Gabr的OmniThread库,但是Delphi正在开发许多线程库.您可以轻松实现自己的并行使用匿名类型.
在您做任何事情之前,请确定慢速部件.请勿触摸执行速度足够快的工作代码.
当我开始使用AsyncCalls将用于冻结UI的单线程应用程序转换为(某种程度的)多线程应用程序时,最大的改进就出现了.
尽管AsyncCalls可以做得更多,但我发现它对于这个非常简单的目的很有用.假设你有一个像这样被阻止的子程序:禁用按钮,执行工作,启用按钮.您将"Do Work"部分移动到本地函数(称之为AsyncDoWork),并添加四行代码:
var a: IAsyncCall; a := LocalAsyncCall(@AsyncDoWork); while (NOT a.Finished) do application.ProcessMessages; a.Sync;
这对你来说是在一个单独的线程中运行AsyncDoWork,而你的主线程仍然可以响应UI(比如拖动窗口或点击Abort).当AsyncDoWork完成时,代码继续.因为我将它移动到本地函数,所有本地变量都可用,代码不需要更改.
这是一种非常有限的"多线程"类型.具体来说,它是双线程.您必须确保Async函数和UI不同时访问相同的VCL组件或数据结构.(我禁用除停止按钮以外的所有控件.)
我不用它来编写新程序.这只是一种非常快速简便的方法,可以使旧程序更具响应性.
使用tstringlist(或类似的)时,设置"sorted:= false"直到需要(如果有的话).看起来很简单......
为字符串和数组智能地使用SetLength().使用FillChar或ZeroMemory优化初始化.
在堆栈上创建的局部变量(例如记录类型)比堆分配的(对象和New())变量更快.
重用对象而不是Destroy然后创建.但要确保管理代码比内存管理器更快!
创建单元测试
验证测试全部通过
描述你的申请
重构寻找瓶颈和记忆
从第2步开始重复(与之前的传球相比)