内存中的字节与字节数组

本文关键字:字节 字节数 数组 内存 | 更新日期: 2023-09-27 18:28:12

下面的代码使用1字节的内存。

byte[] n = new byte[] { 10, 20, 30, 40 }; //memory looks like this 10 | 20 | 30 | 40

与下面的代码相比,它使用了4字节的内存。

byte n1 = 10; // memory looks like this | 10 | 0 | 0 | 0 | 20 | 0 | 0 | 0 | 30 | 0 | 0.....
byte n2 = 20;
byte n3 = 30;
byte n4 = 40;

这是在Visual Studio 2012+2010中测试的,我以为现代编译器应该为我做优化?如果设置间距以使字节秘密地成为非函数int真的比它对数组不起作用更快,那么如果字节数组每个值占用4个字节,从而使字节的整个目的在32位/64位机器上完全无用,它会因此变得更快吗?总结一下:为什么编译器会以这两种不同的方式分配内存,哪一种是低效的方式?第2部分32位/64位机器上的字节的实际用途是什么?如果将其存储在实际的连续字节块中效率很低,而VS在单独声明字节时拒绝这样做。

内存中的字节与字节数组

我认为这里确实有两个问题:

为什么编译器不将四个byte打包到一个Int32

本地变量通常不会针对存储进行优化,而是针对访问速度进行优化。由于访问单个未对齐字节的速度有时在单个指令中是不可能的,而且直到最近(2009年),它比对齐地址慢一个数量级,编译器作者通常使用对齐宽度作为合理的折衷。

除此之外,.Net Framework不是针对x86的,而是针对公共语言基础结构虚拟机的。CLI规范必须支持最低公分母,IA64和ARM不支持非QWORD对齐的内存访问。为此,CLI堆栈"只能存储最小4字节宽的值"(P.330)

他们为什么这么做?我认为潜在的或实际的性能提升超过了内存使用量的增加。考虑到在任何给定范围内64个函数局部的额外限制,应该有强烈的愿望(除了良好的设计)来保持给定范围内的变量数量较小。因此,净开销限制为192字节,这相当于我的系统中使用的额外内存的0.000002%。

请记住,如果您正在访问一个字节数组,那么您实际上是在存储一个指针,即内存地址的宽度(4或8个字节),并直接访问内存。您正在管理哪个字节是哪个字节的语义,并承担这种复杂性。

如何以紧凑的形式存储内容以最大限度地减少内存使用

正如您所指出的,如果您的数据是大量字节,请使用字节数组来避免开销。如果您的数据是不同类型的,请使用允许访问压缩数据的众多类中的一个(脑海中会浮现出BinaryReaderBinaryWriterBitConverterunsafe代码、structStructLayout.Pack字段集)。

如果你有大量的数据,请使用具有固定布局结构的内存映射文件来最大限度地减少内存使用,同时仍然允许数据集大于机器中的内存量。它比正常的内存访问更难吗?是的,是的,但优化是管理内存使用、速度和程序员劳动的平衡行为。最便宜的通常是内存。

或者,花几百块钱,得到足够的公羊,这并不重要。32 GB(newegg售价240美元)可以让您在大多数情况下都不用担心。

当您创建一个n字节或n字节变量的数组时,编译器有不同程度的优化自由度。数组具有固定的内存布局,因为数组是一个密集的数据结构,值之间没有填充。

另一方面,如果您声明字节值,则JITer会尝试将它们在4或8字节边界(x64)上对齐,以确保对齐的内存访问。对于读取访问,对齐与非对齐存储器访问的影响可能约为30%。这是一个有价值的优化。在这种情况下,字节之间的漏洞不是问题,因为更少的空间不会让你更快。正确的内存对齐是获得最佳性能的关键。