【发布时间】:2017-08-01 04:55:46
【问题描述】:
我需要一种方法来限制服务可能分配的内存量,以防止服务使系统饥饿,类似于 SQL Server 允许您设置“最大服务器内存”的方式。
我知道 SetProcessWorkingSetSize 并不完全符合我的要求,但我正试图让它按照我认为应该的方式运行。无论我使用什么值,我的测试应用程序的工作集都不受限制。此外,如果我随后立即调用 GetProcessWorkingSetSize,则返回的值不是我之前指定的值。这是我的测试应用程序使用的代码:
var
MinWorkingSet: SIZE_T;
MaxWorkingSet: SIZE_T;
begin
if not SetProcessWorkingSetSize(GetCurrentProcess(), 20, 12800 ) then
RaiseLastOSError();
if GetProcessWorkingSetSize(GetCurrentProcess(), MinWorkingSet, MaxWorkingSet) then
ShowMessage(Format('%d'#13#10'%d', [MinWorkingSet, MaxWorkingSet]));
没有发生错误,但 GetProcessWorkingSetSize 返回的 Min 和 Max 值都是 81,920。
我尝试在 Flags 参数中使用 QUOTA_LIMITS_HARDWS_MAX_ENABLE ($00000004) 使用 SetProcessWorkingSetSizeEx。不幸的是,如果我在 Flags 中传递 $00000000 以外的任何内容,SetProcessWorkingSetSizeEx 会失败并显示“代码 87。参数不正确”。
我也追求使用 Job Objects 来实现相同的目标。启动子进程时,我在使用作业对象时存在内存限制。但是,我需要服务能够设置自己的内存限制,而不是依赖“启动”服务来做到这一点。到目前为止,我还没有找到一种方法让单个进程创建作业对象,然后将自己添加到作业对象中。这总是会因拒绝访问而失败。
有什么想法或建议吗?
【问题讨论】:
-
我认为您需要为此使用工作。
-
documentation 表示最小值。值必须为 20 * 页面大小(即 4K 页面大小的情况下为 81920)或更大,否则使用最小 20 * 页面大小。 (值以字节为单位。)
-
在我看来,您的做法是错误的。如果您想编写一个不会使系统饿死的服务,请以不需要大量内存的方式编写它。考虑像 SQL 服务器这样的东西(根据问题):它使用大量内存的原因是它故意在内存中缓存尽可能多的数据以加快访问速度。当然,当超出物理内存时,它可以简单地依赖操作系统交换空间,但这会降低效率,因为操作系统不能使用索引表。因此,当您配置 SQL 内存使用时,您实际上只是在配置其内部缓存。
-
你需要问自己的问题是为什么你需要这么多内存?您能否编写代码以更有效地使用内存?强制操作系统更快地换出应用程序使用的内存,或者在较低的栏中报告“内存不足”并不能真正解决根本问题。
-
PS:请注意,当您使用钝器以避免“饿死其他内存进程”时,您会面临以下风险:由于内存不足而为您自己的应用程序造成问题;或者在内核花费更多时间交换您的“体贴应用程序”时使其他进程的 IO 资源挨饿。所以无论你做什么:衡量和比较。
标签: windows delphi memory 64-bit