The go-to way to limit how much memory can be committed on Linux (and other POSIX OSs?) is to limit the virtual address space, in turn limiting how much memory can be reserved. This is likely due to Linux supporting different configurations of overcommitting, which makes it practical to limit how much memory can be committed via the virtual address space instead.
AFAIK there is no way to limit the virtual address space on Windows. The size of the virtual address space is dictated by what hardware you're running on, if you're running a 32-bit application on a 64-bit system, and also depending on the version of Windows. Some sources:
Rule of thumb:
- x64: Windows 8.1 and Windows Server 2012 R2 or later: 128 TB
- Windows Server 2022 and newer supports up to: 4 PB for hosts that support 5-level paging, 256 TB for hosts that support 4-level paging
VirtualMemory.md is a small summary on what values are returned from GlobalMemoryStatusEx() into MEMORYSTATUSEX.
The way I found to limit how much memory that can be committed for a (group of) process(es) is to use Job Objects. Job Objects is also what native Windows Hyper-V containers use to limit memory for both all containers and specific containers.
See JOBOBJECT_BASIC_LIMIT_INFORMATION and JOBOBJECT_EXTENDED_LIMIT_INFORMATION, which contains the following tunable settings:
ProcessMemoryLimit
If the LimitFlags member of the JOBOBJECT_BASIC_LIMIT_INFORMATION structure specifies the JOB_OBJECT_LIMIT_PROCESS_MEMORY value, this member specifies the limit for the virtual memory that can be committed by a process. Otherwise, this member is ignored.
JobMemoryLimit
If the LimitFlags member of the JOBOBJECT_BASIC_LIMIT_INFORMATION structure specifies the JOB_OBJECT_LIMIT_JOB_MEMORY value, this member specifies the limit for the virtual memory that can be committed for the job. Otherwise, this member is ignored.
Process Governor is a popular tool that utilizes Job Object(s) to limit memory for applications.
JobObjectLimitCreateCheck.cpp shows a small example of creating a Job Object that limits the memory for either a single process or all processes in the job, and assigning the current process to that job. Output from that program:
.\JobObjectCreateCheck.exe
No limit
Job Object assigned to the current process
Has limit: 536870912
Implementing resource controls for Windows containers
The Hyper-V backend for Docker on Windows uses Job Objects to limit memory for containers. This does not affect the WSL backend for Docker on Windows, which runs entirely on Linux. To verify how this works, I did a quick experiment with Docker on Windows using the Hyper-V backend with the following minimal Dockerfile (see JobObjectLimitCheck.cpp):
FROM mcr.microsoft.com/windows/servercore:ltsc2022
WORKDIR /app
COPY JobObjectLimitCheck.exe .
CMD JobObjectLimitCheck.exe
$ docker build -t jolc
...
$ docker run jolc
No limit
$ docker run -m 512m jolc
Has job limit
Has limit: 536870912
The --memory-reservation
flag is not supported on Windows:
$ docker run -m 512m --memory-reservation=256m jolc
docker: Error response from daemon: invalid option: Windows does not support MemoryReservation