.net - .NET 中奇怪的数组内存管理

标签 .net windows memory-management

我编写了一个 WPF 应用程序,面向 .NET 4.5.2 64 位。它在 Windows 8.1 Professional 64 位上运行。

该应用程序用于同时录制多个视频。由于视频编码器的速度在运行过程中可能会有很大差异,因此我在内存中创建了一些非常大的字节数组(总共 6 GiB),这足以让我缓冲 40 秒的视频,并且我让编码在单独的线程上进行,因此我不会冒被编码阻止并错过来自摄像机的传入帧的风险。

我在某处读到(字节)数组在 .NET 中是延迟分配的 - 即只写 byte[] foo = new byte[1024*1024];并不意味着立即分配 1 MiB;直到第一次访问时才真正分配内存。虽然我再也找不到在哪里读过那句话了。无论如何,知道这一点,我一定要调用Array.Clear()在我的数组上,这应该强制它们立即分配。我还需要确保缓冲区始终保留在 RAM 中,因此我完全禁用了页面文件。

但由于某种原因,.NET 运行时或 Windows 似乎仍在做一些疯狂的事情:在初始化我的字节数组并对所有字节数组调用 Array.Clear() 之后,我可以在任务管理器中看到 7.4 GiB 正在使用中。它就坐在那里直到我按下“记录”按钮,此时我开始有真实的数据来填充缓冲区。奇怪的是,In Use 内存开始下降到 3.6 GiB 左右,然后又慢慢回升到 7.4 GiB。我的应用程序从来没有丢弃和重新分配数组。另请记住,由于我已禁用页面文件,因此 Windows 没有地方可以调出页面。

这是怎么回事?我该如何解释这种奇怪的现象?

What I saw in Task Manager

最佳答案

What is going on? How should I interpret this weirdness?

这并不奇怪,这就是垃圾收集的工作原理。

当您使用Array.Clear时,您只是将这些字节重置为0(感谢@Martin)。 这并不意味着垃圾收集将在同一时刻发生。如果该数组仍然被引用,则这甚至不会使其符合收集条件。 GC 的运行时间是不确定的。

您所看到的实际上是有道理的,因为您看到一旦您按下“记录”,运行时需要分配更多资源来使用,它首先调用一个集合,然后随着这些字节的消耗而开始缓慢增加通过您的应用程序。

正如其他人在评论中所说,如果您需要对应用程序中管理的内存进行细粒度的粒度,那么您最好使用较低级别的语言,这样您就可以(尽可能地)控制内存的分配和释放内存。

关于.net - .NET 中奇怪的数组内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34174495/

相关文章:

c# - 在没有 SolidColorBrush 的情况下从 Color 获取 Brush

.net - 为什么 Math.Round(2.5) 返回 2 而不是 3?

.net - 将属性更改为方法 - 有副作用吗?

.net - 在同一台计算机上调试TcpClient和TcpListener

windows - 适用于 Windows 的 Logstash 和 Kibana 安装程序

c++ - 自动内存分配如何在 C++ 中实际工作?

c# - 使用 Newtonsoft Json 从流中反序列化多个 json 对象

windows - Git - 推送新的提交并忽略未提交的更改

c - 在 C 中释放结构的函数

delphi - 接口(interface)、匿名方法和内存泄漏