C# 有没有办法将进程的当前工作集扩展到1GB?

C# 有没有办法将进程的当前工作集扩展到1GB?,c#,.net,.net-4.0,C#,.net,.net 4.0,可能重复: 我们希望提前将.NET进程的工作集增加到1GB,以避免页面错误 在.NET中有这样做的方法吗 更新 不幸的是,即使我们调用了,垃圾收集也会绕过MinWorkingSet(请参阅下图中的“Automatic GC.Collect()”)来修剪工作集 在下图中,是否有方法将进程工作集(绿线)锁定为1GB,以避免在向进程分配新内存时出现页面错误(红线)峰值 这将是可怕的原因,因为每次出现页面错误时,它都会将线程阻塞250us,这严重影响了应用程序的性能 更新 引用自:“Windows

可能重复:

我们希望提前将.NET进程的工作集增加到1GB,以避免页面错误

在.NET中有这样做的方法吗

更新

不幸的是,即使我们调用了,垃圾收集也会绕过MinWorkingSet(请参阅下图中的“Automatic GC.Collect()”)来修剪工作集

在下图中,是否有方法将进程工作集(绿线)锁定为1GB,以避免在向进程分配新内存时出现页面错误(红线)峰值

这将是可怕的原因,因为每次出现页面错误时,它都会将线程阻塞250us,这严重影响了应用程序的性能

更新

引用自:“Windows via C/C++,第五版,Jeffrey Richter(Wintellect)”

忽略单个进程对SetProcessWorkingSetSize的调用 除非进程只是尝试清空其工作集。要设置 此限制,请在中指定作业\对象\限制\工作集标志 我是你的成员

本书暗示,设置工作集的唯一方法是将流程分配给作业对象,并设置作业\对象\限制\工作集和最小工作集大小

更新

SetProcessWorkingSetSizeEx与软页面错误完全无关。它只指硬页面错误,因为它阻止当前工作集中的内存被分页到硬盘驱动器

更新


证明了唯一增加工作集的方法是使用C++编写的非常专门的.NET来运行.NET(参见下面的答案).

如果您的问题是,在内存不足的情况下,您的进程的WS修剪过大,您可以通过调用
SetProcessWorkingSetSize
或仅通过设置来解决

不过,您已经展示的是,GC正在减少您的工作集。这告诉我,真正发生的是GC正在取消分配组成WS的页面。如果是这种情况,您将遇到地址空间问题,而不是工作集问题,并且您无法进行任何系统调用来防止它。理想情况下,您应该是这样的能够告诉GC不要将其内存返回操作系统,但是.NET没有这样的功能

要解决地址空间问题,您必须重用已分配的对象。如果您的问题是对象堆太大,很可能是由于集合造成的。例如,与其创建新的数组/列表/字典,不如调用其
Clear
方法并重用它。如果您的问题是字符串,则您可能可以逃脱使用
StringBuilder
s远离LOH


如果你有某些类型的对象,你可以创建很多的,考虑创建一个回收的池。我从来没有做过这样的事情,但是如果我要实现它,我会用一个静态工厂方法创建一个对象,这个对象将一个对象从一个池中拉出来,调用一个初始化器而不是公共构造函数,并在其上设置一个终结器。hat将其放回池中,并将其中的任何引用置零。根据需要,池可能是一个

ConcurrentBag

,以实现您需要调用的/pinvoke,最小值为1 GB(第二个参数)和
配额限制\u硬件\u最小值\u启用
作为第四个参数,确保即使在系统的“高内存压力”条件下,工作集大小也不会低于给定的最小值

系统行为还取决于调用者的权限,具体取决于操作系统版本等。您可能需要
SE_INC_WORKING\u SET_NAME
和/或
SE_INC_BASE_PRIORITY_NAME


另一个(更好的)选择是“在幕后”使用这些API“是您可以找到的.NET包装器。

我认为将进程分配给作业对象和设置可能会起作用。

我认为这里有一个误解:GC释放未使用的内存是好的。仅仅为了在WS度量中看到一个更高的数字而保持它是没有用的。。。您不希望WS中有未使用的内存。您正在为错误的指标进行优化

页面错误的数量没有那么重要,因为存在软错误和硬错误。从磁盘读取的硬故障。软故障在大多数情况下毫无意义。它们是操作系统的一个实现细节。例如,对于您触摸的每个新分配的页面,都会发生软故障

这里有一些证据表明您的红色图表没有显示硬故障:最后显示大约500/秒。您的磁盘无法提供500 IOPs,因此不能是硬故障

您可能只想测量(并减少)硬故障。只有硬故障才会以有意义的方式影响性能

此外,设置WS-limits不会影响GC的工作。GC不是操作系统组件。是一个用户模式库。它与操作系统决定使用什么作为工作集无关。因此,不能通过设置WS-limits使GC不释放内存

那么为什么当GC运行时WS会收缩呢?因为GC删除了一些内存。设置某些WS-limit无法阻止删除内存


在评论中,有人建议GC本身可以调用一些API来缩小工作集。我看不出有任何理由它会这样做。为什么GC会强制页面退出进程?记住:WS和分配的页面是不同的(根本不一样!)。GC可能会释放内存。它不会强制WS收缩。这样做的目的是什么?

我们能找到的唯一方法是在.NET下增加进程的工作集,以减少软页面错误,即在自定义页面下运行整个.NET应用程序。这是一个非平凡的练习,需要大约800行自定义编写的,相当密集的C++代码。C++代码拦截对WI的.NET调用。