CLR内存消耗问题

发布于 2024-10-01 13:05:12 字数 244 浏览 0 评论 0原文

CLR 的问题之一是它在缺乏 RAM 时表现出极其糟糕的行为(当托管进程的某些内存被调出时,这会导致整个系统完全冻结,甚至无法访问 Ctrl-Alt-Del 屏幕)我认为原因是 GC 尝试构建可到达对象的图表并尝试扫描进程的所有内存,从而导致大量页入/页出操作。
这给我的 .NET 程序带来了一个问题,因为当输入数据很大时它会消耗大量 RAM。

我更愿意向用户显示“内存不足”消息,而不是完全挂起他的系统^_^
有什么办法可以实现这一点吗?

One of issues with CLR is it's extremely bad behavior in the lack of RAM (when some of memory of managed process gets paged out, this leads to the total freeze of the whole system, even Ctrl-Alt-Del screen can't be accessed. I assume the reason is GC which tries to build graph of reachable objects and tries to scan all memory of the process, causing massive page in/page out operations).
This makes a problem for my .NET program, coz it can consume lots of RAM when input data is huge.

I'd prefer to show a "not enough memory" message to the user, rather than completely hang his system ^_^
Is there any way to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一个人的旅程 2024-10-08 13:05:12

使用MemoryFailPoint,您可以告诉.NET您将需要一定数量的内存。但问题是,即使这个系统也包含交换空间。

我相信在这里达到你想要达到的目标是非常困难的。比如说,您将使用一些系统指示器和性能指示器来找出有多少物理内存可用,并基于此执行一些任务。如果完成此检查后,另一个进程进入了物理内存,则您原来的计算不再适用,并且您的一些内存将被推送到交换。

我确实有一个建议。您可以设置一个配置设置,其中包含应用程序允许使用的最大内存量吗?有了这个,您可以:

  1. 尝试根据网络连接(如果您的应用程序是网络服务器)等计算出您的应用程序消耗了多少资源,并根据最大内存消耗限制连接数量,或者

  2. 您可以有第二个线程每隔 10 秒或每分钟检查一次使用 GC.GetTotalMemory() 的总内存消耗,并在达到该最大值后开始拒绝连接(同样,如果您的应用程序是网络服务器)。< /p>

这应该是一个配置设置,而不是可用物理内存量等,因为您不知道计算机上正在运行哪些其他应用程序。

With MemoryFailPoint, you can tell .NET you are going to need a certain amount of memory. The problem though is that even this system includes swap space.

I believe that it is very difficult to achieve what you want to achieve here. Say, you would use some system indicators and performance indicators to find out how much physical memory is available and based on that, perform some tasks. If after you've completed this check a different process comes in a grabs physical memory, your original calculations do not apply anymore and some of your memory is going to be pushed to swap.

I do have a suggestion. You could have a configuration setting with the maximum allowed amount of memory to be used by the application? With this, you can:

  1. Try to figure out how much resources your application consumes based on e.g. a network connection (if your application is a network server) and throttle the number of connections based on the maximum memory consumption, or

  2. You could have a second thread running that checks ever 10 seconds or minute of so the total memory consumption with GC.GetTotalMemory() and start rejecting connections (again, if your application is a network server) once you get to that maximum.

This should be a configuration setting instead of e.g. the amount of physical memory available, because you do not know what other applications are running on the machine.

哥,最终变帅啦 2024-10-08 13:05:12

有一些系统调用可以获取进程的大小和计算机上的 RAM 帐户,这可能会有所帮助。

过去有很多关于编写可以处理分页的 GC 的研究,但我预计它们永远不会发布,因为现在 RAM 变得越来越大。 (基本的理想是不收集任何被分页的对象,并尝试在操作系统将其分页之前收集页面上的所有对象。但是您需要知道分页可能指向的所有对象)

您可以使用结构数组,然后传递索引,以减少拥有的对象数量,从而减少 GC 必须遵循的指针数量。仅当 RAM 中有大量所需类型的数据时,这才值得。

There are system calls to get the size of a process and the account of RAM on a machine that may help.

There used to be a lot of research on writting GCs that could cope with paging, but I expect they will never ship as RAM is getter so big these days. (The basic ideal was not to collect any objects that are paged out, and to try to collect all objects on page just before the OS paged it out. But you need to know all objects that may be pointed to by a paged out object.)

You may be able to use arrays of structs and then pass about the indexes so as to reduce the number of objects you have, and hence the number of pointers the GC have to follow. This is only worthwhile if you have a LOT of data of the same type you need in RAM.

゛时过境迁 2024-10-08 13:05:12

在 Windows 中,您可以使用作业对象对进程可以分配的虚拟内存量设置硬性限制。当达到此限制时,CLR 将自动进行垃圾收集,如果无法释放足够的空间,则会抛出 OutOfMemoryException。您还可以限制进程的工作集而不是虚拟内存。这允许进程根据需要分配尽可能多的内存,但它将被换出而不是消耗 RAM,并且系统不会挂起。我已经成功地使用作业对象来实现此目的(在运行大型作业时保持机器响应)。

要从 .NET 创建作业对象,您必须使用对 Win32 API 的 PInvoke 调用。这篇关于 CodeProject 的文章解释了该过程。

In Windows, you can use a Job Object to put a hard limit on the amount of virtual memory that a process can allocate. The CLR will automatically garbage collect when it hits this limit, and throw an OutOfMemoryException if it cannot free enough space. You can also limit the working set of a process instead of the virtual memory. This allows the process to allocate as much as it likes but it will get swapped out instead of consuming RAM and the system won't hang. I've used Job Objects successfully for exactly this purpose (keeping the machine responsive while running large jobs).

To create job objects from .NET, you have to use PInvoke calls to the Win32 API. This article on CodeProject explains the procedure.

躲猫猫 2024-10-08 13:05:12

让 IIS 托管该进程并使用 IIS 中的内存控制来限制所使用的内存量。希望这将更频繁地强制执行 GC,并最大限度地减少长时间运行 GC 会话的需要。我认为这种行为是由于您的应用程序从代际角度使用内存的方式造成的,就像大量小对象一样,这些小对象 1) 寿命较长,2) 在内存中移动。

类似 .NET/CLR 内存控制问题和解决方案的其他链接

配置 .NET CLR RAM 使用情况
限制 .Net CLR 内存使用
虚拟和物理内存/OutOfMemoryException
使用 GC.AddMemoryPressure() 防止 OutOfMemoryException?
强制对数组进行垃圾回收,C#
垃圾收集瓶颈示例
抑制 C# 垃圾回收
如何分析 .net 垃圾收集器?

如果您使用的是大对象堆 (LOH)

.NET 集合和大对象堆 (LOH)< /a>
大对象堆碎片

Have IIS host the process and use the memory controls in IIS to limit the amount of memory used. Hopefully this will force GC more often and minimize the need for a long-running GC session. I would imagine that this behavior is due to how your app is using memory from a generational aspect, as in a large number of small objects that are 1) long-lived and 2) getting moved around in memory.

Other links to similiar .NET/CLR memory control issues and solutions

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?

In case you are using the Large Object Heap (LOH)

.NET Collections and the Large Object Heap (LOH)
Large Object Heap Fragmentation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文