CLR的一个问题是,在缺少RAM的情况下是非常糟糕的行为(当托管进程的某些内存被调出时,这会导致整个系统完全冻结,甚至Ctrl-Alt-Del屏幕都可以'我可以假设原因是GC尝试构建可到达对象的图形并尝试扫描进程的所有内存,从而导致大量页面进/出操作。) 这对我的.NET程序来说是一个问题,因为当输入数据很大时它会消耗大量的RAM。
我宁愿向用户显示“内存不足”的消息,而不是完全挂起他的系统^ _ ^
有没有办法实现这个目标?
答案 0 :(得分:3)
使用MemoryFailPoint
,您可以告诉.NET您将需要一定数量的内存。但问题是即使此系统也包含交换空间。
我相信在这里实现你想要达到的目标是非常困难的。比如说,您将使用一些系统指示器和性能指标来确定可用的物理内存量,并根据该值执行某些任务。如果在完成此检查后,另一个进程会占用物理内存,则原始计算将不再适用,并且您的一些内存将被推送到交换。
我有建议。您可以使用应用程序使用的最大允许内存量进行配置设置吗?有了这个,你可以:
尝试根据以下因素确定应用程序消耗的资源量。网络连接(如果您的应用程序是网络服务器)并根据最大内存消耗限制连接数,或
您可以运行第二个线程,检查总是使用GC.GetTotalMemory()
的内存消耗10秒或分钟,并开始拒绝连接(再次,如果您的应用程序是网络服务器)到那个最大值。
这应该是配置设置而不是例如可用的物理内存量,因为您不知道机器上正在运行的其他应用程序。
答案 1 :(得分:2)
有系统调用可以获取进程的大小以及可能有用的计算机上的RAM帐户。
曾经有很多关于编写可以应对分页的GC的研究,但我预计它们永远不会发布,因为RAM这些日子里的内存如此之大。 (基本的理想是不收集任何被分页的对象,并尝试在操作系统分页之前收集页面上的所有对象。但是你需要知道被分页可能指向的所有对象。 out object。)
您可以使用结构数组,然后传递索引以减少您拥有的对象数量,从而减少GC必须遵循的指针数量。如果您在RAM中需要大量相同类型的数据,这是值得的。
答案 2 :(得分:1)
在Windows中,您可以使用Job Object对进程可以分配的虚拟内存量进行硬限制。 CLR在达到此限制时将自动进行垃圾收集,如果无法释放足够的空间,则抛出OutOfMemoryException。您还可以限制进程的工作集而不是虚拟内存。这允许进程尽可能多地分配但是它将被换出而不是消耗RAM而系统不会挂起。我已成功使用Job Objects来实现此目的(在运行大型作业时保持机器响应)。
要从.NET创建作业对象,必须使用对Win32 API的PInvoke调用。这个article on CodeProject解释了这个程序。
答案 3 :(得分:0)
让IIS托管进程并使用IIS中的内存控件来限制使用的内存量。希望这会更频繁地强制GC并最小化对长时间运行的GC会话的需求。我认为这种行为是由于你的应用程序如何使用内存来自一代人的方面,就像大量小对象一样长寿,2)在内存中移动。
Configure .NET CLR RAM usage
Restricting .Net CLR memory usage
Virtual and Physical Memory / OutOfMemoryException
Preventing OutOfMemoryException with GC.AddMemoryPressure()?
Force garbage collection of arrays, C#
examples of garbage collection bottlenecks
Suppressing C# garbage collection
how to profile .net garbage collector?
.NET Collections and the Large Object Heap (LOH)
Large Object Heap Fragmentation