如何在64位.NET进程中设置MinWorkingSet和MaxWorkingSet?

Con*_*ngo 5 .net c# working-set

如何为64位.NET进程设置MinWorkingSet和MaxWorking?

ps我可以为32位进程设置MinWorkingSet和MaxWorking集,如下所示:

[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);

[DllImport("KERNEL32.DLL", EntryPoint = "GetCurrentProcess", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr MyGetCurrentProcess();

// In main():
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, int.MaxValue, int.MaxValue);
Run Code Online (Sandbox Code Playgroud)

cas*_*One 6

您所要做的就是更改您的声明,如下所示:

[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", 
    SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, 
    long dwMinimumWorkingSetSize, long dwMaximumWorkingSetSize);
Run Code Online (Sandbox Code Playgroud)

原因是因为函数定义SetProcessWorkingSetSize:

BOOL WINAPI SetProcessWorkingSetSize(
  _In_  HANDLE hProcess,
  _In_  SIZE_T dwMinimumWorkingSetSize,
  _In_  SIZE_T dwMaximumWorkingSetSize
);
Run Code Online (Sandbox Code Playgroud)

请注意,它不使用a DWORD(作为32位整数)而是使用a SIZE_T,其定义如下:

指针可指向的最大字节数.用于必须跨越指针的整个范围的计数.此类型在BaseTsd.h中声明如下:

typedef ULONG_PTR SIZE_T;
Run Code Online (Sandbox Code Playgroud)

这意味着它是64位值,因此能够更改为a long并使该功能在64位系统上运行.另外,从MSDN标题为" Common Visual C++ 64位迁移问题 "的部分:

size_t,time_tptrdiff_t是64位Windows操作系统上的64位值.

但是,这会带来一些困境,因为您不希望编译特定于平台的程序集(即PITA).你可以通过利用(你已经在做的)上的EntryPoint字段来解决这个问题,以获得两个方法声明:DllImportAttribute

[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", 
    SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize32(IntPtr pProcess, 
    int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);

[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", 
    SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize64(IntPtr pProcess, 
    long dwMinimumWorkingSetSize, long dwMaximumWorkingSetSize);
Run Code Online (Sandbox Code Playgroud)

现在您有两个单独的签名.但是,知道要调用哪个签名仍然是个问题.您不希望在任何地方进行条件检查.为此,我建议创建一个方法来执行检查并调用它.

您将要使用的Is64BitProcess属性Environment来做出此决定.不要使用该Is64BitOperatingSystem物业.您需要前者,因为32位进程可以在64位操作系统上运行,并且您希望确保您的代码具有弹性; 只是检查操作系统是否为64位并不能给你全部图片.

  • 或者您可以使用`UIntPtr`并将其传递给它. (2认同)

Han*_*ant 6

不要对此进行说明,只需Process.CurrentProcess.MinWorkingSet直接使用该属性即可.

非常高的赔率,这不会有任何区别.如果机器有足够的RAM,软分页故障是完全正常的并且很快就能解决.我的笔记本电脑需要约0.7微秒.你无法避免它们,它是像Windows这样的demand_paged虚拟内存操作系统的行为.非常便宜,只要有一个随时可用的免费页面.

但如果它"闪烁"你编程性能,那么你需要考虑它不可用的可能性并在另一个进程中触发硬页面错误.如果必须从另一个进程中窃取RAM页面,其页面内容必须存储在页面文件中并且必须首先重置为零,否则寻呼错误会变得昂贵.这可以很快加起来,几百微秒并不罕见.

"没有免费午餐"的基本法则,你需要运行更少的流程或购买更多的内存.后一种选择是理智的选择,8千兆字节让你今天回来大约75美元.完全偷.