【问题标题】:Delphi 7 Function - String or ShortString? Integer or Word? [closed]Delphi 7 函数 - 字符串还是短字符串?整数还是字? [关闭]
【发布时间】:2013-04-07 07:43:06
【问题描述】:

我是一个“性能”狂热的程序员,并且有一个基本的理论问题:Delphi 7 是否有一些“方法”来识别所使用的字符串类型并自动定义正确的类型?

例如,当您知道函数的结果字符串长度总是小于 255 时,您会使用:

function SomeFunction: String;function SomeFunction: ShortString;?

同样的想法:

function SomeFunction(Num: Integer): Integer;function SomeFunciont(Num: Byte): Word;?

【问题讨论】:

  • 询问“我如何优化我还没有做的事情?”是没有意义的。编写你的代码。如果它执行得太慢,请使用分析器来确定性能问题所在,然后考虑如何解决该瓶颈。
  • Ken,您能详细解释一下“profiler”吗?你的意思是 FastMM4 之类的东西?
  • 不,我不是指 FastMM4。 (FastMM 是内存管理器,而不是分析器。)谷歌“分析器 Delphi”。在此处发布问题之前,您需要自己开始进行基础研究。
  • 从您最近的问题来看,您正在寻找错误的地方来提高性能。让你的程序表现更好的方法是使用好的算法。您最近的问题显示了一些异常低效的算法。始终从查看您的算法开始。
  • 欢迎来到 Stack Overflow。我从没想过“表演爱好者”会问这种问题。您应该为自己发现而感到兴奋。也许您喜欢成为一名性能爱好者,而您的问题应该是关于如何回答性能问题。

标签: string performance delphi variables integer


【解决方案1】:

永远不要在函数中使用shortstring,即使在 Delphi 7 中也是如此。

当用作函数结果时,始终会复制 shortstring 的完整内容(即所有字符)。

因此它会比使用普通的string 变量慢,后者只会增加字符串的内部引用计数,而不复制字符。

由于大多数 Delphi RTL/VCL 库都使用 string,因此在代码中使用 shortstring 将为这些方法的每次调用添加大量转换,而使用普通 string 则不会出现这种情况.并且在调用Windows API的时候,delphi的string类型已经是零端了,所以会避免任何分配和转换,这在使用shortstring时是必须的。

因此,您必须知道shortstring 在所有版本的 Delphi 中都比较慢,特别是如果您使用FastMM4 作为内存管理器:当使用shortstring 进行任何 RTL/VCL/API 调用时,Delphi 编译器实际上会分配一些隐藏的临时string,因此从堆中分配一个缓冲区...远没有效率:最好立即使用字符串!

如果您认为 string 很慢(由于原子引用计数或内存分配对多线程不太友好),请不要使用 shortstring,而是使用其他结构 - 请参阅我的回答 https://stackoverflow.com/a/6076407/458259 并且从不使用http://delphitools.info/samplingprofiler/之类的工具进行优化而不进行分析

对于使用 integer 值的函数,byte/word/cardinal/integer 不会产生速度差异。我的习惯是尽可能使用integer,这将适合CPU 寄存器大小。只有Int64 类型的值会更慢,在 32 位以下,因为它将使用 2 个寄存器或堆栈上的临时变量。

更新:在较新版本的 Delphi 中,您将拥有“inline”关键字,这可能有助于提高返回此类类型的小函数的性能。从 Delphi 2009 开始,字符串是 Unicode 并且 shortstring 已被弃用,因为它已固定到系统非 Unicode 应用程序代码页。仅当您确切知道自己在做什么,并且能够使用 Alt-F2 并查看生成的 asm 代码,猜测调用了哪些隐藏的 RTL 函数时,才使用 shortstring

【讨论】:

  • 谢谢阿诺!这正是我想知道的!
  • 您没有将短字符串作为函数结果的假设是正确的,至少在当前的优化级别下是正确的。但是,如果您排除它,那么在 ansistring 不能利用显着的写时复制优势的情况下,短字符串应该仍然更快,如果仅仅是因为引用计数过程调用和分配只是额外的开销。 Shortstring 有很多缺点,但它的主要问题是在名称上标注的,它不是“noperformancestring” :) 我也不明白 fastmm 和它有什么关系。
  • @MarcovandeVoort 在 Delphi 7(OP 版本)中,堆管理器非常慢,因此在这种情况下,字符串分配比堆栈分配的短字符串慢得多。如果你在 Delphi 7 中使用 FastMM4,这个缓慢因素就会消失。我从来没有写过从不使用短字符串,只是从不使用函数、RTL 或 API。 ShortString 将为其大多数操作(如赋值、连接等)在堆栈上创建长度为 255 个字符的临时副本,因此没有什么好处,除非您深入了解 Delphi RTL。大多数类型,堆栈分配的字符缓冲区是一个更好的主意。
  • 但是堆栈上的副本是空闲的或接近空闲的(只是添加到 stckframe 的大小),而在类似的情况下,基于 ansistring 的 temp 涉及调用帮助程序和堆管理器,除非它是单独的用作 1:1 副本。 (顺便说一句,恕我直言,fastmm 的收益有时被夸大了)
  • @MarcovandeVoort 与旧的 Borland MM 相比,对于大多数分配,对于单线程应用程序,FastMM4 增益约为 3x-5x。关于在栈上copy一个shortstring,它不是免费的,恐怕你没有踩到生成的asm。内存是在堆栈帧序言中内联分配的,但是复制是通过 RTL 调用和嵌套的 move() 完成的 - 请参阅 system.pas 中的 _PStrCpy() - 而 string 复制只是一个lock inc [refCount]快得多。一般来说,_PStr* 函数或编译器生成的操作码较慢(例如,现代 CPU 上的 rep movsb)。
【解决方案2】:

Delphi 7 是否有某种方法可以识别所使用的字符串类型并自动定义正确的类型?

即使它提高了性能,编译器也不会进行此类转换。为此,它需要执行所谓的数据流分析。换句话说,它需要分析数据如何在程序中流动,并对变量中可能包含的内容进行推理。

但编译器不执行这种分析,因此无法对 你描述的类型。

【讨论】:

  • @user539484 你不喜欢这个答案的什么地方?它是否无法解决所提出的问题?还是事实不正确?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多