Delphi XE能否生成比Delphi 2007更快的代码?

15

我一直在使用 Delphi 2007 开发不需要 Unicode 的项目。

最近我在想,为什么大家都在赞扬 Delphi XE 呢?因为:

  • 每个人都在赞扬它;
  • 内置 SVN 支持。

然而我想知道,编译器是否有任何改进可以使 Delphi XE 比 Delphi 2007 产生更快的代码,我指的是这样的事情:

  • 更好的死代码消除(Delphi 2007 还不错,但不能消除 100% 的死代码)
  • 循环展开(类似于 C 的 O3 优化级别)
  • 自动内联短程序
  • 多线程代码中的开销更少

编辑

在这个页面上:http://www.embarcadero.com/products/delphi/whats-new

列出了:改进了编译器性能,那具体有哪些改进呢?


XE重新构建的可执行文件之所以更快,其中一个原因就是它使用Unicode API,因为本地内部API是Unicode(在基于NT的Windows和后来的版本中)。D2007调用Ansi API,并且每个带有字符串参数的调用可能会导致潜在的内部Unicode翻译。 - Ondrej Kelle
3
Win32字符串API调用很少成为瓶颈。 - David Heffernan
最近我在Delphi中进行了一些数字计算,编写了gold版本作为CUDA代码的基准测试。很抱歉那里没有太多的Unicode :-)。不过你提出了一个很好的观点,我一直认为ansistring更快,因为它使用的内存较少,但是忘记了翻译问题。 - Johan
@David 当然,性能差异取决于你实际调用它们的次数。有些应用程序可能会频繁调用,而其他一些则不会。我只是认为值得一提。 - Ondrej Kelle
@所有人,非常感谢你们提供了一系列非常有价值的答案。 - Johan
循环展开现在并不总是一个好主意。请参阅http://agner.org/optimize中的optimizing_assembly.pdf文件,第101页:“Core2和Nehalem处理器在代码不超过64字节的循环上表现更好。如果循环展开使得循环超过64字节,则会降低Core2的性能。(请参见手册3:“Intel、AMD和VIA CPU的微架构”。)。” - Arnaud Bouchez
5个回答

17

我的两个观点:

1. 关于我们的开源ORM框架

在使用Delphi 7、Delphi 2007和Delphi 2010编译器运行我们的单元测试时,我发现Delphi 2007比Delphi 7有一些速度改进,但Delphi 2007和2010之间没有明显差异。发现Delphi 2010生成的代码甚至有点慢。我手头没有Delphi XE编译器,但我猜它与Delphi 2010差不多-主要是关于泛型的错误修复,如果我没记错的话。

当我编写低级Pascal代码并使用分析器时,我会花费很多时间在asm视图(Alt-F2)中。因此,我通常会注意到Delphi编译器版本之间的差异。

我认为主要的改进确实是方法和函数/过程的inline关键字,在Delphi 2007中可用而在Delphi 7中不可用。另一个改进是更积极的寄存器重用。

浮点数生成的代码仍然很慢,有时很糟糕(即使不再需要FWAIT,也仍然会产生,内联浮点代码甚至可能比不内联还要糟糕

我们的框架和所有这些测试有趣之处在于它处理了大量数据,使用自己编写的低级单元,在非常调整的Pascal中进行编码以获得最佳性能。提供的单元测试(超过5,400,000个单独的测试)在真实数据上工作(数字转换或UTF-8文本处理),包括低级转换、文本解析、对象分配、多线程和客户端/服务器方向等各种各样的进程。因此,在这里,编译器生成的代码确实有所不同。
代码主要在我们的框架内部。我们使用我们自己的RawUTF8字符串类型,而不是通用字符串。因此,瓶颈不在VCL也不在Windows API,而仅在纯Delphi编译代码中。实际上,我们避免了大多数API调用,甚至对于UTF-8编码或数字转换也是如此。
当然,我尝试了设置PUREPASCAL条件的基准测试,即不运行asm中的优化部分,而是仅依赖于“纯Pascal”代码。
另一个关于速度的好实验是编写和分析我们的SynLZ压缩单元。通过这种LZ压缩算法的优化实现,压缩速度比zip快20倍,解压速度比zip快3倍。实际上,它与LZO竞争压缩比和解压速度,但在压缩方面比LZO快得多:SynLZ能够以与解压缩相同的速度压缩数据。这样对称的实现在压缩领域非常罕见。

这涉及到整数算术和位逻辑、哈希表中的填充和查找以及内存复制。

我们编写了一些经过优化的Pascal代码,然后使用Delphi 7和Delphi 2009进行编译。

Delphi 2009生成的代码比Delphi 7更快,而且明显地更好,寄存器重用效果更好。

通过手动调整汇编代码,我们实现了更好的性能。例如,使用zip压缩6 KB的XML文件时,速度为14 MB/s,使用LZO为185 MB/s,使用SynLZ的Delphi 2009 Pascal版本为184 MB/s,使用我们最终调整的asm版本的SynLZ为256 MB/s。

结论:

对于涉及整数处理、文本解析或内存的代码生成,我认为Delphi XE比Delphi 7更快,但应该与Delphi 2007差不多。内联是主要的新特性,可以大大加速代码。

但对于真实应用程序,速度增加不会很明显。在某些特定情况下可能会增加10或20%,但不会更多。算法始终是提高性能的关键。Delphi 7已经是一个很好的编译器。

对于浮点运算,Delphi编译器现在已经过时。我希望64位编译器中的SSE代码会改变这里的结果。

直接回答你的问题,在Delphi 2010或XE中,没有自动内联或自动循环展开,据我所知。而多线程代码中的开销不是编译器的一部分,而是在库(FastMM4,引用计数等)中。因此,我认为Delphi XE并不比Delphi 2007产生更快的代码。


我很想知道在x64上更好的浮点代码生成会有什么不同。 - David Heffernan
接受的答案是因为它具有分析背景,虽然这个问题很难判断,但是这个帖子中有许多好的答案。 - Johan
@Marco SEE仍然是64位的,因此下一个编译器可能缺乏扩展类型支持。 - Arnaud Bouchez
关于SSE性能的问题,你可以猜测它在计算复杂运算方面会更加出色。目前最新的Javascript引擎已经超越了当前的Delphi编译器(使用即时编译成SSE),你必须手写SSE才能达到可接受的结果。@David - Arnaud Bouchez
据我所知,64位编译器中将会有一个汇编程序,但不是作为Pascal块内联汇编块,而是作为普通的汇编函数或过程。请看David I所说的:“虽然我们将无法在一个方法中混合使用Pascal和汇编代码,但将有内部64位汇编程序。不再有扩展类型:(如果这让你困扰(它肯定让我困扰),请给你当地的Delphi代表写信。”http://www.thedelphigeek.com/2011/03/delphi-down-under.html - Arnaud Bouchez
显示剩余5条评论

10

我的非正式测试 Delphi XE 编译器显示,在涉及泛型使用的许多情况下,代码生成更加正确,而且解决了在 Delphi 2009、2010 时期困扰编译器的某些编译器内部故障(bug)。在许多情况下,使用泛型的 Delphi 2010 代码,链接到包中,并在 IDE 中反复重建,将导致损坏的 DCP 文件输出或神秘的编译器内部错误。

如果是我,我会在发布说明中写道 “我们修复了这些 bug”。(我撤回了“有史以来最好的”这个说法,因为人们认为我把它作为自己前雇主 Embarcadero 的广告语。)我想所有这些都被平滑地转化为“性能”一词中,其中性能被理解为“正确性”,“可靠地执行其工作并无故障”。

至于速度,就运行时速度和编译器性能而言,我没有注意到从 Delphi 2009、2010 或 XE 中分析代码的统计显着差异,也没有注意到编译器的性能在“构建项目更快”的方面有所提升。

由于您询问关于Delphi 2007的情况,您应该知道有一个很大的类型更改(String = AnsiString,变成了String = UnicodeString)。对于相同的代码,某些事情将会变慢,某些事情将会更快,如果不了解您的代码,100%无法确定重新编译您的2007代码到2010后会发生什么。如果您以前经常使用WideString,并且现在可以使用UnicodeString,那么您的代码将会更快,因为UnicodeString的性能比WideString好得多。一些Delphi程序在win32内部静默地(几乎是看不见的)将ansi数据转换为unicode数据,例如当您使用Memo公共控件时,会花费很长时间在您的代码中。另一方面,之前使用字节大小字符串的一些事情,现在将使用字大小字符串,因此某些地方的内存使用将增加,并且某些操作可能会变慢。

对于已正确移植的代码(如果您为2007编写了它们,则必须对大多数应用程序进行一些更改才能使它们在XE中构建),最可能的净结果是“原始性能”的微小净减少。

然而,Delphi XE可以在IDE中重复构建项目,甚至反复构建,而不会出现问题,并且从未崩溃过。Delphi 2007经常崩溃。Delphi 2007还有数百个令人讨厌的编译器错误,会让我发疯。编译代码速度甚至不是升级的主要原因,可靠性才是。

在我使用的大型项目中,Delphi 2007、2009和2010在某些复杂包集的第二次或第三次重建时经常崩溃。在2009年和2010年,重度使用泛型的包特别容易使IDE崩溃。XE很稳定,即使我将其与重型泛型代码一起使用,这也是发布说明可能会谈到的一种“性能”改进。我称之为“错误修复”。让我们直言不讳吧。


我正在尝试解释用户所询问的文本的含义。 - Warren P
2
我会在发布说明中写下最坚实、可靠、经过充分测试的编译器版本,只是为了告诉先前版本的客户“嘿,我们一直在开玩笑吗?” - user160694
2
如果将来我对雇主销售的产品的优点或缺点发表任何意见,无论是正面还是负面,我都会在帖子中声明我的关联。我不会因为你购买或不购买而获得额外的钱,而且我不是RAD团队的成员,我从事其他产品的工作。我也是Delphi用户,无论我是否在Embarcadero工作,我都会支持Delphi。如果我没有受雇于Embarcadero,我会更加强烈地表达我的观点,因为那时我就不必对“苛刻”的人如此礼貌了。 - Warren P
1
被踩:公司员工宣传公司产品 - 无论他在公司中的职位如何,都是一种利益冲突。我猜SO也应该为这类帖子提供一种“标记”。此外,随着产品接近“生命周期结束”状态,因为新版本即将发布,我看到了越来越多的“购买XE”的活动,我想知道这是自发的还是市场推动的努力。 - user160694
1
希望你不是为Emb营销工作。 “我们修复了漏洞”。好的。你的意思是直到那时你卖给我有缺陷的版本,对吧?谢谢,我没有用假钱交换给你。我知道任何程序都有漏洞,但将新版本宣传为“最终我们修复了我们之前卖给你的那些漏洞”有点傻。我感激Emb的人在这里写技术解决方案,而不是告诉我们购买实际版本,当然,这总是“最好的”。甚至D2005也被认为比以前的版本更好... - user160694
显示剩余6条评论

5

我没有看到任何关于代码生成方面的显著改进证据。自从Delphi 5以来,我不知道有什么非常显著的代码生成改进。事实上,我从Delphi 2开始升级后从未发现我的代码运行更快。


谢谢David,从你所参与的项目来看,你可能比大多数人更早地注意到了。 - Johan
2
尽管代码生成基本没有改变,但Delphi的新版本要好得多。 - David Heffernan
无法同意这个答案。当比较Delphi XE和Delphi 7时,您可以感受到字符串操作(例如更快的PosEx、IntToStr等例程)和内存管理(由于FastMM)方面的巨大改进。 - Linas
@Linas 非常好的观点。事实上,大多数知情人士都使用FastMM与D7(以及D6、D5等)。我个人在代码的关键区域不使用堆分配,所以FastMM对我来说没有太大的影响(除了实际上能够与LARGE_ADDRESS_AWARE一起工作!) - David Heffernan
1
@Linas 这不是重点:问题是关于生成的代码,而不是关于库。 - Arnaud Bouchez
显示剩余4条评论

3

Delphi编译器在今天已经非常过时,正在进行重写。自XE以来的改进看起来很微小,编译器实际上无法充分利用最新的处理器能力和指令集(它大多停留在80386时代,但某些RTL代码使用手写汇编语言以利用更现代的功能)。与之前版本相比,XE编译器可能更可靠(因为D7质量变化很大),但要想整体性能有所提升,需要完全改造编译器,使其适应21世纪的发展。

这个工作正在进行中,但目前尚不清楚下一个版本是否只有更新的64位编译器,还是32位编译器也有新的代码库。


由于Intel/AMD处理器的架构,对于大多数常见的Pascal代码(涉及文本、数据和整数),速度提升并不来自使用比386更新的操作码。只有在浮点运算和大数据处理(如图像处理)方面,新的指令集(如SSE)才会产生影响。在新的64位编译器中将有SSE过程:这里将会有一些真正的变化。 - Arnaud Bouchez
即使手写汇编中的RTL代码仍在80386区域内:它不使用SSE或其他任何东西,只使用经过优化的x86和x87汇编语言以及优化对齐内存访问。这里没有MMX / SSE的迹象。 ;)但当前的32位编译器已经做得很好了:如死代码消除,聪明的寄存器使用和窥孔优化。 - Arnaud Bouchez
@A.Bouchez,我很好奇,什么是peephole优化? - Johan
1
只要他能够解释并且不是简单地属于“Delphi崇拜者”类别,试图对每个指出其神产品中真实问题的人发出诅咒,那么那个点踩者本可以解释为什么这样做。Embarcadero本身已经决定重写编译器,如果它不过时,他们就不会这样做了。 - user160694
编译器可能会以几种方式变得过时。当然,我认为无法轻松更新到64位的代码库意味着它无法轻松更新以支持新的处理器、指令和新的优化。从头开始重写总是一项漫长、昂贵且风险高的任务,通常在代码真正过时时才会放弃。BC++编译器在过去几年中也失去了很多地位,被VC++和GCC(更不用说英特尔)所取代。 - user160694

2
这是一个指向Embarcadero的链接。

http://www.embarcadero.com/products/delphi/whats-new

在页面的下方,引用了“语言、编译器和库的增强”一节。他们提到了编译器的改进,但没有太多具体内容。不过,他们没有提到的也许就是你想要的答案。如果有什么重大改进,他们很可能会吹嘘一番。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接