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

时间:2021-07-19 14:41:02

I am trying to figure out if there could be situations where using "packed array of [type]" could be advantageous if trying to save memory.

我试图弄清楚是否可能存在使用“打包的[类型]数组”在尝试节省内存时可能有利的情况。

You can read that on Win32 bit, it is not the case: http://docwiki.embarcadero.com/RADStudio/XE4/en/Internal_Data_Formats#Dynamic_Array_Types

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

Generally speaking, it would seem to me runtime code for dynamic arrays would be fasterif never using padding between items. But since I believe default alignment in Delphi/64bit is 8byte, it would seem to be there would be a a chance that you some day could not count on dynamic arrays containg e.g. booleans being "packed" by default

一般来说,在我看来动态数组的运行时代码会更快,永远不会在项目之间使用填充。但是,由于我认为Delphi / 64bit中的默认对齐是8byte,似乎有一天你有可能不会依赖于包含例如动态数组的动态数组。布尔值默认为“打包”

1 个解决方案

#1


1  

First of all I think you need to be careful how you read the documentation. It has not been updated consistently and the fact that some parts appear specific to Win32 can in no way be used to infer that Win64 differs. In fact, for the issues raised in your question, there are no substantive differences between 32 and 64 bit.

首先,我认为您需要注意如何阅读文档。它没有一致地更新,并且某些部分看起来特定于Win32的事实绝不能用于推断Win64的不同。事实上,对于您提出的问题,32位和64位之间没有实质性差异。

For Delphi, using packed on an array does not change the padding between successive elements. The distance between two adjacent elements of an array is equal to SizeOf(T) where T is the element type. This holds true irrespective of the use of the packed modifier. And using packed on an array does not even affect the alignment of the array.

对于Delphi,在数组上使用packed不会更改连续元素之间的填充。数组的两个相邻元素之间的距离等于SizeOf(T),其中T是元素类型。无论使用填充改性剂如何,这都适用。并且在数组上使用打包甚至不会影响数组的对齐。

So, to be completely clear and explicit, packed has no impact at all when used on arrays. The compiler treats a packed array in exactly the same way as it treats a non-packed array.

因此,要完全清楚明确,打包在阵列上使用时根本没有任何影响。编译器处理打包数组的方式与处理非打包数组的方式完全相同。

This statement seems to be at odds with the documentation. The documentation states:

这个陈述似乎与文档不一致。文件说明:

Alignment of Structured Types

结构类型的对齐

By default, the values in a structured type are aligned on word- or double-word boundaries for faster access.

默认情况下,结构化类型中的值在字或双字边界上对齐,以便更快地访问。

You can, however, specify byte alignment by including the reserved word packed when you declare a structured type. The packed word specifies compressed data storage. Here is an example declaration:

但是,您可以通过在声明结构化类型时包含保留字来指定字节对齐。打包字指定压缩数据存储。这是一个示例声明:

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

But consider this program:

但考虑一下这个程序:

{$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.

The output of which, using Delphi XE2, is:

使用Delphi XE2的输出是:

0
8

So, using packed with arrays, in contradiction of the documentation, does not modify alignment of the type.

因此,与文档相反,使用压缩数组不会修改类型的对齐方式。

Note that the above program, when compiled by Delphi 6, has output

请注意,上述程序在由Delphi 6编译时具有输出

0
1

So it would appear that the compiler has changed, but the documentation has not caught up.

所以看起来编译器已经改变了,但文档还没有赶上。

A related question can be found here: Are there any difference between array and packed array in Delphi? But note that the answer of Barry Kelly (an Embarcadero compiler engineer at the time he wrote the answer) does not mention the change in compiler behaviour.

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


Generally speaking, it would seem to me runtime code would be faster if never using padding between items.

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

As discussed above, for arrays there never is padding between array elements.

如上所述,对于数组,数组元素之间永远不会有填充。

I believe default alignment in Delphi/64bit is 8 byte.

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

The alignment is determined by the data type and is not related to the target architecture. So a Boolean has alignment of 1. A Word has alignment of 2. An Integer has alignment of 4. A Double has alignment of 8. These alignment values are the same on 32 and 64 bit.

对齐由数据类型确定,与目标体系结构无关。因此,布尔值的对齐方式为1.字的对齐方式为2.整数的对齐方式为4.双方的对齐方式为8.这些对齐值在32位和64位上相同。

Alignment has an enormous impact on performance. If you care about performance you should, as a general rule, never pack data structures. If you wish to minimise the size of a structure (class or record), put the larger elements first to minimise padding. This could improve performance, but it could also worsen it.

对齐对性能产生巨大影响。如果您关心性能,通常应该从不打包数据结构。如果希望最小化结构(类或记录)的大小,请先放置较大的元素以最小化填充。这可以提高性能,但也可能使其恶化。

But there is no single hard and fast rule. I can imagine that packing could improve performance if the thing that was packed was hardly ever accessed. And I can, more readily in fact, imagine that changing the order of elements in a structure to group related elements could improve performance.

但没有一个单一的硬性规则。我可以想象,如果打包的东西几乎没有被访问过,打包可以提高性能。事实上,我可以更容易地想象,将结构中的元素顺序更改为对相关元素进行分组可以提高性能。

#1


1  

First of all I think you need to be careful how you read the documentation. It has not been updated consistently and the fact that some parts appear specific to Win32 can in no way be used to infer that Win64 differs. In fact, for the issues raised in your question, there are no substantive differences between 32 and 64 bit.

首先,我认为您需要注意如何阅读文档。它没有一致地更新,并且某些部分看起来特定于Win32的事实绝不能用于推断Win64的不同。事实上,对于您提出的问题,32位和64位之间没有实质性差异。

For Delphi, using packed on an array does not change the padding between successive elements. The distance between two adjacent elements of an array is equal to SizeOf(T) where T is the element type. This holds true irrespective of the use of the packed modifier. And using packed on an array does not even affect the alignment of the array.

对于Delphi,在数组上使用packed不会更改连续元素之间的填充。数组的两个相邻元素之间的距离等于SizeOf(T),其中T是元素类型。无论使用填充改性剂如何,这都适用。并且在数组上使用打包甚至不会影响数组的对齐。

So, to be completely clear and explicit, packed has no impact at all when used on arrays. The compiler treats a packed array in exactly the same way as it treats a non-packed array.

因此,要完全清楚明确,打包在阵列上使用时根本没有任何影响。编译器处理打包数组的方式与处理非打包数组的方式完全相同。

This statement seems to be at odds with the documentation. The documentation states:

这个陈述似乎与文档不一致。文件说明:

Alignment of Structured Types

结构类型的对齐

By default, the values in a structured type are aligned on word- or double-word boundaries for faster access.

默认情况下,结构化类型中的值在字或双字边界上对齐,以便更快地访问。

You can, however, specify byte alignment by including the reserved word packed when you declare a structured type. The packed word specifies compressed data storage. Here is an example declaration:

但是,您可以通过在声明结构化类型时包含保留字来指定字节对齐。打包字指定压缩数据存储。这是一个示例声明:

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

But consider this program:

但考虑一下这个程序:

{$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.

The output of which, using Delphi XE2, is:

使用Delphi XE2的输出是:

0
8

So, using packed with arrays, in contradiction of the documentation, does not modify alignment of the type.

因此,与文档相反,使用压缩数组不会修改类型的对齐方式。

Note that the above program, when compiled by Delphi 6, has output

请注意,上述程序在由Delphi 6编译时具有输出

0
1

So it would appear that the compiler has changed, but the documentation has not caught up.

所以看起来编译器已经改变了,但文档还没有赶上。

A related question can be found here: Are there any difference between array and packed array in Delphi? But note that the answer of Barry Kelly (an Embarcadero compiler engineer at the time he wrote the answer) does not mention the change in compiler behaviour.

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


Generally speaking, it would seem to me runtime code would be faster if never using padding between items.

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

As discussed above, for arrays there never is padding between array elements.

如上所述,对于数组,数组元素之间永远不会有填充。

I believe default alignment in Delphi/64bit is 8 byte.

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

The alignment is determined by the data type and is not related to the target architecture. So a Boolean has alignment of 1. A Word has alignment of 2. An Integer has alignment of 4. A Double has alignment of 8. These alignment values are the same on 32 and 64 bit.

对齐由数据类型确定,与目标体系结构无关。因此,布尔值的对齐方式为1.字的对齐方式为2.整数的对齐方式为4.双方的对齐方式为8.这些对齐值在32位和64位上相同。

Alignment has an enormous impact on performance. If you care about performance you should, as a general rule, never pack data structures. If you wish to minimise the size of a structure (class or record), put the larger elements first to minimise padding. This could improve performance, but it could also worsen it.

对齐对性能产生巨大影响。如果您关心性能,通常应该从不打包数据结构。如果希望最小化结构(类或记录)的大小,请先放置较大的元素以最小化填充。这可以提高性能,但也可能使其恶化。

But there is no single hard and fast rule. I can imagine that packing could improve performance if the thing that was packed was hardly ever accessed. And I can, more readily in fact, imagine that changing the order of elements in a structure to group related elements could improve performance.

但没有一个单一的硬性规则。我可以想象,如果打包的东西几乎没有被访问过,打包可以提高性能。事实上,我可以更容易地想象,将结构中的元素顺序更改为对相关元素进行分组可以提高性能。