【发布时间】:2015-12-09 08:57:30
【问题描述】:
我编写了一个 WPF 应用程序,目标是 .NET 4.5.2 64 位。它在 64 位 Windows 8.1 Professional 上运行。
该应用程序用于同时录制多个视频。因为视频编码器的速度在运行过程中会发生很大的变化,所以我在内存中制作了一些非常大的字节数组(总共 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 没有地方可以调出页面。
发生了什么事?我应该如何解释这种怪异?
【问题讨论】:
-
数组是在 .NET 中延迟分配的 不,这是操作系统处理虚拟内存的结果。当您在 .NET 中分配一个数组时,您会保留所有需要的虚拟内存。但是,有些虚拟内存可能不会分配给物理 RAM。为了更好地了解发生了什么,我建议您查看流程的性能计数器;而不是整个计算机的性能。顺便问一下,你有什么问题吗?
-
可能有人认为您为这项工作选择了错误工具。使用一种编程语言来抽象您对内存的使用,然后不得不与操作系统抗争以防止它完成它的工作。如果您想显式控制内存,您应该在较低的抽象级别上工作,您可以在其中使用 Windows API,例如
VirtualLock
标签: .net windows memory-management