My program can allocate suddenly a lot of RAM based on usage. I want to limit the RAM it can take from the system.
I saw here: Limit RAM usage to python program
But it works only for Unix. Any solution for Windows?
My program can allocate suddenly a lot of RAM based on usage. I want to limit the RAM it can take from the system.
I saw here: Limit RAM usage to python program
But it works only for Unix. Any solution for Windows?
A Job object supports limiting the committed memory of a process. In Python, we can implement this via PyWin32 or ctypes.
Note that prior to Windows 8 a process can only be in a single Job. A couple of common cases where this is a concern include the py.exe launcher (the default association for .py files), which runs python.exe in a Job, and the Task Scheduler service, which runs each task in a Job.
import sys
import warnings
import winerror
import win32api
import win32job
g_hjob = None
def create_job(job_name='', breakaway='silent'):
hjob = win32job.CreateJobObject(None, job_name)
if breakaway:
info = win32job.QueryInformationJobObject(hjob,
win32job.JobObjectExtendedLimitInformation)
if breakaway == 'silent':
info['BasicLimitInformation']['LimitFlags'] |= (
win32job.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)
else:
info['BasicLimitInformation']['LimitFlags'] |= (
win32job.JOB_OBJECT_LIMIT_BREAKAWAY_OK)
win32job.SetInformationJobObject(hjob,
win32job.JobObjectExtendedLimitInformation, info)
return hjob
def assign_job(hjob):
global g_hjob
hprocess = win32api.GetCurrentProcess()
try:
win32job.AssignProcessToJobObject(hjob, hprocess)
g_hjob = hjob
except win32job.error as e:
if (e.winerror != winerror.ERROR_ACCESS_DENIED or
sys.getwindowsversion() >= (6, 2) or
not win32job.IsProcessInJob(hprocess, None)):
raise
warnings.warn('The process is already in a job. Nested jobs are not '
'supported prior to Windows 8.')
def limit_memory(memory_limit):
if g_hjob is None:
return
info = win32job.QueryInformationJobObject(g_hjob,
win32job.JobObjectExtendedLimitInformation)
info['ProcessMemoryLimit'] = memory_limit
info['BasicLimitInformation']['LimitFlags'] |= (
win32job.JOB_OBJECT_LIMIT_PROCESS_MEMORY)
win32job.SetInformationJobObject(g_hjob,
win32job.JobObjectExtendedLimitInformation, info)
def main():
assign_job(create_job())
memory_limit = 100 * 1024 * 1024 # 100 MiB
limit_memory(memory_limit)
try:
bytearray(memory_limit)
except MemoryError:
print('Success: available memory is limited.')
else:
print('Failure: available memory is not limited.')
return 0
if __name__ == '__main__':
sys.exit(main())
assign_job(create_job()). Then limit_memory(memory_limit) configures a memory limit that applies to all processes in the job. Subsequently, calling your run_pipeline function will be subject to the memory limit. Note that by default the job is created in silent breakaway mode, so only the current process will be in the job, i.e. you don't have to worry about child processes being affected by this limit.Assertion failed: error not defined [8] (C:\ci\zeromq_1599741307349\work\src\ip.cpp:481) I got this while running above codeI had about the same problem as the OP, except that I wanted to limit the amount of physical RAM used, not virtual. @eryksun's answer and limit_memory() function work great, but limit the total amount of allocatable memory (virtual memory). Here is an additional function to his/her code that limits the amount of physical memory (the "working set").
def limit_working_set(memory_limit):
if g_hjob is None:
return
info = win32job.QueryInformationJobObject(g_hjob, win32job.JobObjectBasicLimitInformation)
info['MinimumWorkingSetSize'] = 50 * 4096 # default minimum value
info['MaximumWorkingSetSize'] = memory_limit
info['LimitFlags'] = (win32job.JOB_OBJECT_LIMIT_WORKINGSET)
win32job.SetInformationJobObject(g_hjob, win32job.JobObjectBasicLimitInformation, info)
By default this can only be done by Administrators. To enable this functionality for regular users it's possible to provide them with the needed rights through the group policy editor, as described in this procgov issue.
limit_working_set function they get an error pywintypes.error: (1314, 'SetInformationJobObject', 'A required privilege is not held by the client.')procgov) I found this issue. If regular users are allowed to "Increase scheduling priority" policy it's possible for them to limit the workingset.