可能重复:
有没有什么办法来强制进程的工作集是1GB的C ++?
我们想增加一个.NET过程1GB的工作集,提前,以避免页面错误。
有没有办法在.NET中做到这一点?
更新
不幸的是,看来,即使我们做一个呼叫SetProcessWorkingSetSizeEx ,垃圾收集修剪工作集倒无妨,绕过MinWorkingSet(见“自动GC.Collect的()如下图)。
在下面的图片中,有没有办法锁定进程工作集(绿线)到1GB,以避免在分配新内存到进程时出现页面错误(红色线)秒杀?
这将是真棒,其原因是,每次发生页面错误,它会阻止线程250US,这伤害到应用程序的性能不好。
更新
引用自: “通过C / C ++的Windows,第五版,杰弗里里希特(Wintellect的)”
调用由一个单独的进程SetProcessWorkingSetSize被忽略,除非进程只是试图清空其工作集。 要设置此限制,在LimitFlags成员指定JOB_OBJECT_LIMIT_WORKINGSET标志。
本书暗示设置工作集的唯一方法是通过分配过程中的作业对象和设置JOB_OBJECT_LIMIT_WORKINGSET和MinimumWorkingSetSize。
更新
SetProcessWorkingSetSizeEx有绝对无关,与软页面错误。 它仅是指硬页面错误,因为它可以防止内存在目前的工作集被调出到硬盘驱动器。
更新
事实证明,以增加工作集的唯一方法是.NET使用非常专业的运行CLR主机 C ++编写的(见我的回答如下)。
为了达到你想要什么,你需要调用/ PInvoke的SetWorkingSetSizeEx与1 GB为最小(第二PARAM)和QUOTA_LIMITS_HARDWS_MIN_ENABLE
作为第四PARAM这可以确保工作集大小不会去下面你即使在“高内存压力”的条件给了最低系统。
该系统的行为还取决于来电者的特权,这取决于操作系统版本等你可能需要SE_INC_WORKING_SET_NAME
和/或SE_INC_BASE_PRIORITY_NAME
!
它使用这些API“幕后”的另一种(更好的)选项是一个.NET包装,你可以找到这里 。
如果你的问题是,你的过程,获取其在WS低内存情况下修剪过agressively,你可以通过调用照顾它SetProcessWorkingSetSize
或只设置Process.CurrentProcess.MinWorkingSet
。
你已经证明什么,不过,是你的工作组得到由GC降低。 这告诉我,真正的情况是GC被重新分配,使您的WS的页面。 如果是这种情况,你有一个地址空间问题,而不是一个工作组的问题,而且也没有系统调用你可以阻止它。 理想情况下,你将能够告诉GC不其内存返回到操作系统,但.NET没有这样的功能。
为了解决地址空间的问题,你将不得不重用你已经分配的对象。 如果你的问题是与大对象堆,这很可能是由于集合。 例如,而不是创建一个新的数组/列表/字典,调用它的Clear
方法和重用。 如果你的问题是一个字符串,你也许能逃脱使用StringBuilder
s到留出LOH的。
如果你有某种类型的对象的创建大量的,考虑创建它们的池得到回收。 我从来没有做过这样的事情,但如果我是来实现它,我将创建与翻出一池的对象并调用一个初始化程序而不是公共构造静态工厂方法的对象,并把一个终结它是把它放回池中,并空出它的任何引用。 根据不同的需求,池可能是ConcurrentBag<WeakReference<T>>
。
我认为,分配过程中的作业对象和设置JOB_OBJECT_LIMIT_WORKINGSET
和MinimumWorkingSetSize
可能会奏效。
我们可以发现,以增加工作集的过程中.NET下,能减少软页面错误的唯一方法,就是运行自定义下的整个.NET应用程序CLR主机 。 这是一个非平凡的工作,需要约800的自定义编写,相当致密的C ++代码行。 在C ++代码截获.NET调用Win32的内存管理方法,改变.NET运行时的行为,所以它不会释放内存积极,因为它通常会。
这有招致所有软页面错误的效果时,应用程序启动时,使正常的应用程序执行期间,在.NET应用软页面错误数降至几乎为零。
这意味着应用程序可能是内存饿了,但它的运行速度更快。 换句话说,我们正在牺牲内存使用量增加的实时性能。
我认为这里有一个误区一:GC释放未使用的内存是不错的 。 这是没有用的,放心将其保留看到在WS指标更高一些......你不想在WS未使用的内存。 你是优化了错误的度量。
因为有软,硬故障页面故障的数量是不是有意义。 硬盘故障从磁盘读取。 软故障是指没有在大多数情况下。 他们是操作系统的实现细节。 例如,对于每一个新分配的页面你触摸软故障发生。
下面是一些证据表明,你的红图没有显示硬故障:在结束它显示约500 /秒。 您的磁盘不能提供500个眼压所以不能硬故障。
你可能想只测量(减少)硬故障。 以有意义的方式只有硬故障影响性能。
此外,设置WS限制不会影响GC做什么。 GC未操作系统组件。 是是用户模式库。 这无关什么操作系统决定作为工作组使用。 出于这个原因,你不能让GC不是通过设置WS限制释放内存。
那么,为什么WS收缩GC运行时? 因为GC 删除一些内存。 设置一些限制WS无法阻止的记忆缺失。
在评论这启示了GC本身可能调用一些API缩小工作集。 我看不到任何理由的,为什么它会做到这一点。 为什么会产生GC力页出的过程? 记住:WS和分配的页面是不一样的(在所有!)。 该GC会释放内存。 它不强制WS萎缩。 它会带来什么样的目的?
文章来源: Is there a way to expand the current WorkingSet of a process to 1GB? [duplicate]