我编写了一个 .NET 4.5 应用程序,它缓冲来自 Kinect v2 的颜色、红外和深度数据,对其进行一些处理,然后以未压缩的形式将其转储到磁盘;.NET 应用程序还启动 ffmpeg 作为子进程,并将颜色数据传输给它以编码为 H.264。
由于我没有使用 SSD,因此视频数据的到达速度比写入磁盘的速度要快。但没关系,当我的 RAM 不足时,我可以接受丢弃视频帧。我唯一的要求是,无论我保留什么,大部分都是连续的 8 到 10 秒的视频片段。因此,我在 .NET 4.5 应用程序中添加了一些逻辑,当我没有足够的 RAM 来缓冲连续的 8 到 10 秒的视频(大约 1.5 到 2 GB)时,开始丢弃视频帧。
而且,为了防止页面抖动,我完全禁用了分页文件。这样我就只剩下 16 GB 的物理 RAM。
我的问题是,即使有了这个机制,有时当 Windows 8.1 因 RAM 不足而崩溃时,我的 .NET 应用程序或 ffmpeg 子进程仍然会被终止,因为很明显,当我的应用程序有大量视频数据要写入磁盘时,它会使用最多的 RAM。有没有办法告诉 Windows 我的进程比其他进程更重要,这样 Windows 就会首先终止其他不太重要的进程?
答案1
当所有 RAM 都被使用时,Windows 不会终止进程。实际发生的情况是进程无法分配内存并崩溃。
发生这种情况的原因是,您的所有物理内存都在使用中,并且由于页面文件被禁用,内存管理器不再能够写入未使用的页面。这使您的物理 RAM 保持满负荷状态,并且当您的进程或当时正在运行的任何其他程序尝试分配页面时,它会失败。一些应用程序会崩溃。
Technet 的此演示文稿解释道: http://channel9.msdn.com/Events/TechEd/NorthAmerica/2011/WCL405
当您使用完所有内存后,页面文件可以充当过度承诺的后盾,从而防止应用程序崩溃。
虚拟内存几乎是现代操作系统分配资源的基础,因此它就是将正在使用的内容放在 RAM 中,并将内容移入和移出磁盘。
实际上只有两个答案:
- 重新启用页面文件并增加计算机上的 RAM,以减少磁盘抖动。
- 减少应用程序的内存要求。
底线是 RAM 只是另一级缓存,有关虚拟内存、页面文件、内存映射文件的所有内容基本上都归结为这一点:如果内存不足,则需要添加更多内存。
答案2
进入 Windows 工具面板和高级设置并禁用不需要的东西,例如窗口效果(如果还没有),然后获取 Sysinternals 进程资源管理器和/或系统监视器来查找并关闭浪费 CPU 或内存的任何无关紧要的东西。
更重要的是,使用进程资源管理器和/或系统监视器来观察程序的执行情况,并准确了解程序失败的位置和原因。哪个线程内存不足并首先终止 - 主程序还是 ffmpeg 部分?是否有特定的 dll 或其他共享资源意外地膨胀?或者执行是否正确进行,只是吞噬了超出其能力的数据?
更准确地找出问题的本质可能会为您指明解决方案的方向。例如,您可以更积极地实施丢帧策略,同时更好地优化 8-10 秒块标准,以降低总体 RAM 开销
最后的建议:也许可以考虑切换到 Linux,同时重新启用页面文件(linux 称之为交换空间,在我看来这听起来更有趣,就像交换会或类似的东西!)祝你好运。