字节与内存中的字节数组

时间:2013-08-19 05:01:41

标签: c# byte

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

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

vs下面的代码使用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拒绝这样做。

2 个答案:

答案 0 :(得分:6)

我假设这里有两个问题:

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

本地变量通常不会针对存储进行优化,而是针对访问速度进行优化。由于在单个指令中有时无法访问单个未对齐字节,until recently(2009),is an order of magnitude slower比对齐地址,编译器作者通常使用对齐宽度作为合理权衡。< / p>

除此之外,.Net Framework不是针对x86而是针对Common Language Infrastructure虚拟机。 CLI规范必须支持最低公分母,IA64和ARM不支持非QWORD对齐内存访问。为此,CLI堆栈“只能存储至少4字节宽的值”(P.330)。

他们为什么这样做?我认为潜在或实际的性能增益超过了内存使用量的增加。鉴于64 functional locals在任何给定范围内的额外限制,应该有一个强烈的愿望(除了良好的设计)以保持给定范围内的变量数量很小。因此,净开销限制为192个字节,相当于我系统中使用的额外0.0000002%的内存。

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

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

正如您所指出的,如果您的数据是大量字节,请使用字节数组以避免开销。如果您的数据类型不同,请使用允许访问打包数据的众多类别之一(BinaryReaderBinaryWriterBitConverterunsafe code,{{3}一切都浮现在脑海中。

如果您有大量数据,请使用具有固定布局结构的structs with the StructLayout.Pack field set以最小化内存使用,同时仍允许数据集大于计算机中的内存量。它比正常的内存访问更难吗?是的,是的 - 但优化是管理内存使用,速度和程序员劳动的平衡行为。最便宜的通常是记忆。

或者,花费几百美元并获得足够的内存,这无关紧要。对于大多数情况,32 GB(newegg上240美元)允许相当多的不关心。

答案 1 :(得分:3)

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

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