C#System.Buffer.BlockCopy内存问题?

Oli*_*rdt 6 c# buffer garbage-collection memory-leaks

我有一个困扰我现在几天的问题.我曾试图谷歌这个问题,但到目前为止还没有找到任何解决方案,甚至没有一个人有同样的问题.

似乎C#方法System.Buffer.BlockCopy给你留下了某种内存鬼.我有这样的方法:

private float[,] readFloatArray2 (byte[] b) {
   int floatSize = sizeof(float);
   float[,] v = new float[2, (b.Length / 2) / floatSize];
   System.Buffer.BlockCopy(b, 0, v, 0, b.Length);

   return v;
}
Run Code Online (Sandbox Code Playgroud)

将字节数组转换为2D浮点数组.先前从流中读取数据.我已将问题定位为System.Buffer.BlockCopy方法.

如果我删除BlockCopy命令,应用程序使用的内存将是一半大小.这意味着字节数组仍然存在并不是我的错.因为没有BlockCopy命令,字节数组正常死亡.无论如何都会创建float数组(包含或不包含复制的信息).

我不太确定这是否是BlockCopy命令或GC的问题,因为我还试图调用System.GC.Collect(); 在BlockCopy之后,它也完美无缺(我知道你不应该这样做......这就是为什么我在这里要求建议).

我也不会打扰,但问题涉及几百兆.

除了内存问题,该方法工作得很好.有谁知道导致内存问题的原因是什么?

问候和提前感谢oli

ps:我使用.NET4.0与Visual Studio 2010 PRO和WIN7 ...不知道这是否相关.

Cod*_*aos 3

我发现问题出在System.Buffer.BlockCopy方法上。如果我删除该BlockCopy命令,应用程序使用的内存将减少一半。这意味着字节数组仍然存在并不是我的错。因为如果没有该BlockCopy命令,字节数组就会正常消亡。

我不同意这个结论。我看到几个阶段:

  1. 字节数组存在并且已填充数据
  2. 您分配了浮点数组,但尚未填充数据。
  3. 您用数据填充浮点数组
  4. 字节数组不再被引用,但尚未被收集
  5. 字节数组已收集。

字节数组的生存期不受BlockCopy.

步骤 2 保留并提交虚拟内存。因此提交大小在此步骤中会增加。但由于数组的内容从未被写入,并且完全由00字节组成,因此 Windows 内存管理器不会为其分配任何物理内存。它只是指出这些页面完全由00s 组成。

浮点数组的物理内存仅在步骤 3 中分配。如果添加一个循环来初始化数组中的每个字段,您将获得相同的效果。


除了实际问题之外,我还有一些设计建议:

  1. 重复使用缓冲区。GC 对于小的短寿命对象有好处,但对于大的短寿命对象则非常糟糕。这意味着您不应使用分配和返回大型数组的函数。相反,将它们作为参数,以便可以重用现有数组。
  2. 如果您正在使用音频数据(似乎很可能),我不会使用固体二维数组。我会使用数组的数组。其中内部数组表示单个缓冲区中的样本,外部数组表示缓冲区。这样做有两个优点:

    • 您可以轻松编写仅在单个通道上运行的代码。
    • 实体二维数组的索引速度很慢,因此通常也更快。
  3. 您真的想一次读取所有数据吗?我会以几千字节为单位进行读取。