【问题标题】:Does the order you declare your class variables affect how memory will be allocated?您声明类变量的顺序会影响内存的分配方式吗?
【发布时间】:2016-07-17 15:37:04
【问题描述】:

我偶然发现了以下内容,摘自本书

Joseph Albahari 和 Ben Albahari (O'Reilly) 的 C# 6.0 简述。

版权所有 2016 Joseph Albahari 和 Ben Albahari,978-1-491-92706-9。

我没有看到那里提到它,但是根据经验,它不会遵循 - 您应该始终按照大小的降序声明类型中的变量,以便避免内存浪费被指出?

我的意思是,如果我做对了,我们通常都应该在设计类型时考虑到这一点。


更新:

我想出了下面的sn-p来证明上面是对还是错。然而,我预计 S2 的大小会有所不同(以支持书中所说的)。

public struct S1
{
    public byte b;
    public long l;
}

public struct S2
{
    public long l;
    public byte b;
}

[StructLayout(LayoutKind.Explicit, Size = 9)]
public struct S3
{
    [FieldOffset(0)]
    public byte b;

    [FieldOffset(1)]
    public long l;
}

S1 s1 = new S1();
S2 s2 = new S2();
S3 s3 = new S3();

Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(s1)); //prints 16
Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(s2)); //prints 16
Console.WriteLine(System.Runtime.InteropServices.Marshal.SizeOf(s3)); //prints 9

【问题讨论】:

  • "在您的类型中按大小降序排列" 不完全。从包装的角度来看,short, short, int, longlong, int, short, short 一样好。请记住,优化数据以减少内存可能会对性能产生重大影响。
  • @AlexD:感谢您的补充。您能否详细说明不浪费内存并遵循上述指南会对性能产生重大影响?
  • 我很确定 CPU 不喜欢处理小于字大小的数据,因此虽然您可以节省空间,但性能会受到影响
  • 那么(你们两个),从你们的角度来看——这种行为/知识的意义是什么?
  • @Veverke 这取决于硬件。粗略地说,当您从内存中读取一个字节时,周围的一些字节也会被读取/缓存。因此,如果您有byte x, byte y 并一个接一个地访问它们,它可能会比byte x, long, long, long, byte y 快得多。但这是一个单独的主题:)。

标签: c# clr


【解决方案1】:

这本书的摘录颇具误导性。这意味着 7 个字节被“浪费”了,但这与字段的顺序没有任何关系。您会考虑交换订单,将long 成员放在首位。但这并不能完成任何事情,这 7 个字节仍然未使用。

计算结构的布局和大小,以便 long 仍然与数组中的 8 对齐。换句话说,A[] 的元素也需要对齐。这仅在结构长度为 16 个字节时才有效。或者换句话说,交换字段只是将未使用的 7 个字节移动到结构的末尾。

C# 中的任何结构都具有隐含的 [StructLayout(LayoutKind.Sequential)] 属性。您将不得不使用 LayoutKind.Explicit 来强制字段的故意错位。请注意成本,未对齐的字段可能非常昂贵,会使读写速度减慢 3 倍。当字段跨越 L1 高速缓存行边界时发生。如果处理器不支持未对齐的访问,则更多,更多,今天没有太大的问题,因为 Itanium 不在图片中。而且您失去了从 CLR 规范中获得的任何原子性保证。您不能故意错位引用类型(如字符串)的字段,这会破坏垃圾收集器。

如果结构有 3 个或更多成员,它会变得更有趣。现在,您确实可以通过订购它们来取得成功。就像一个字节,long,int,按这个顺序需要 20 个字节。如果重新排列为 byte, int, long 超过 16 个字节,则 int 适合填充。如果您使用 LayoutKind.Auto 覆盖,则 CLR 将为您执行此操作。

【讨论】:

  • Hans,您是在专门讨论结构,但是,据我了解,这种行为不仅仅针对结构。作者声称在自定义类型(类)中也会发生同样的情况。
  • 一个类在默认情况下总是有 LayoutKind.Auto 所以已经得到了最好的布局。其他一切都一样。
猜你喜欢
  • 2011-11-12
  • 1970-01-01
  • 2014-08-27
  • 2013-02-26
  • 1970-01-01
  • 2020-11-04
  • 1970-01-01
  • 2012-09-08
  • 2017-02-26
相关资源
最近更新 更多