Delphi 64位内部数据格式/动态数组



我正试图弄清楚,如果试图节省内存,使用"[type]的压缩数组"是否会有好处。

你可以在Win32位上读到,事实并非如此:http://docwiki.embarcadero.com/RADStudio/XE4/en/Internal_Data_Formats#Dynamic_Array_Types

一般来说,在我看来,动态数组的运行时代码将是fasterif,从不在项之间使用填充。但是,由于我相信Delphi/64bit中的默认对齐是8字节,因此似乎有一天你可能无法指望动态数组包含例如布尔值,默认情况下"打包"

首先,我认为您需要小心阅读文档。它没有得到一致的更新,而且某些部分似乎是Win32特有的,这一事实决不能用来推断Win64的不同。事实上,对于您的问题中提出的问题,32位和64位之间没有实质性差异。

对于Delphi,在数组上使用packed不会改变连续元素之间的填充。数组的两个相邻元素之间的距离等于SizeOf(T),其中T是元素类型。无论使用填充改性剂,这一点都成立。在数组上使用packed甚至不会影响数组的对齐。

因此,为了完全清楚和明确,packed在数组上使用时根本没有影响。编译器处理压缩数组的方式与处理非压缩数组的方法完全相同。

这一说法似乎与文件不一致。文件说明:

结构化类型的对齐

默认情况下,结构化类型中的值在单词或双字边界,实现更快的访问。

但是,您可以通过包含保留的当您声明一个结构化类型时,word压缩。压缩的单词指定压缩数据存储。下面是一个示例声明:

type TNumbers = packed array [1..100] of Real;

但考虑一下这个程序:

{$APPTYPE CONSOLE}
type
  TNumbers = packed array [1..100] of Real;
type
  TRec = record
    a: Byte;
    b: TNumbers;
  end;
begin
  Writeln(Integer(@TRec(nil^).a));
  Writeln(Integer(@TRec(nil^).b));
  Readln;
end.

使用DelphiXE2,其输出为:

08.

所以,将packed和数组一起使用并不会修改类型的对齐方式,这和文档不符。

注意,上面的程序,当用Delphi6编译时,有输出

01.

因此,编译器似乎发生了变化,但文档并没有跟上。

这里可以找到一个相关的问题:Delphi中的数组和压缩数组之间有什么区别吗?但请注意,Barry Kelly(编写答案时是Embarcadero编译器工程师)的答案并没有提到编译器行为的变化。


一般来说,在我看来,如果从不在项之间使用填充,运行时代码会更快。

如上所述,对于数组,数组元素之间从不存在填充。

我相信Delphi/64bit中的默认对齐方式是8字节。

对齐由数据类型决定,与目标体系结构无关。因此布尔值的对齐方式为1。一个单词的对齐方式为2。整数的对齐方式为4。Double的对齐方式为8。这些对齐值在32位和64位上是相同的。

对齐对性能有着巨大的影响。如果您关心性能,一般来说,您应该永远不要打包数据结构。如果您希望最小化结构(类或记录)的大小,请将较大的元素放在首位,以最小化填充。这可以提高性能,但也可能使性能恶化

但没有一条硬性规定。我可以想象,如果打包的东西几乎从未被访问过,那么打包可以提高性能。事实上,我可以更容易地想象,将结构中元素的顺序更改为与元素相关的组可以提高性能。

最新更新