14 Manage System Processes in OML4Py Using psutil
If you find that your Python process is consuming too many of your machine's resources, or causing your machine to crash, you can get information about, or set limits for, the resources Python is using.
The Python system and process utilities library psutil
is a
cross-platform library for retrieving information on running processes and system
utilization, such as CPU, memory, disks, network, and sensors, in Python. It is useful
for system monitoring, profiling, limiting process resources, and the management of
running processes.
The function psutil.Process.rlimit
gets or
sets process resource limits. In psutil
, process resource limits are
constants with names beginning
with psutil.RLIMIT_
. Each resource is controlled by a soft limit and
hard limit tuple.
For example, psutil.RLIMIT_AS
represents the maximum size
(in bytes) of the virtual memory (address space) used by the process. The default limit
of psutil.RLIMIT_AS
can be -1 (psutil.RLIM_INFINITY
).
You can lower the resource limit of psutil.RLIMIT_AS
to prevent your
Python program from loading too much data into memory, as shown in the following
example.
Example 14-1 Resource Control with psutil.RLIMIT_AS
import psutil
import numpy as np
# Get the current OS process.
p = psutil.Process()
# Get a list of available resources.
[attr for attr in dir(psutil) if attr[:7] == 'RLIMIT_']
# Display the Virtual Memory Size of the current process.
p.memory_info().vms
# Get the process resource limit RLIMIT_AS.
soft, hard = p.rlimit(psutil.RLIMIT_AS)
print('Original resource limits of RLIMIT_AS (soft/hard): {}/{}'.format(soft, hard))
# Check the constant used to represent the limit for an unlimited resource.
psutil.RLIM_INFINITY
# Set resource RLIMIT_AS (soft, hard) limit to (1GB, 2GB).
p.rlimit(psutil.RLIMIT_AS, (pow(1024,3)*1, pow(1024,3)*2))
# Get the current resource limit of RLIMIT_AS.
cur_soft, cur_hard = p.rlimit(psutil.RLIMIT_AS)
print('Current resource limits of RLIMIT_AS (soft/hard): {}/{}'.format(cur_soft, cur_hard))
# Define a list of sizes to be allocated in MB (megabytes).
sz = [5, 10, 20]
# Define a megabyte variable in bytes.
MB = 1024*1024
# Allocate an increasing amount of data.
for val in sz:
stmt = "Allocate %s MB " % val
try:
print("virtual memory: %d MB" % int(p.memory_info().vms/MB))
m = np.arange(val*MB/8, dtype="u8")
print(stmt + " Success.")
except:
print(stmt + " Fail.")
raise
# Delete the allocated variable.
del m
# Raise the soft limit of RLIMIT_AS to 2GB.
p.rlimit(psutil.RLIMIT_AS, (pow(1024,3)*2, pow(1024,3)*2))
# Get the current resource limit of RLIMIT_AS.
cur_soft, cur_hard = p.rlimit(psutil.RLIMIT_AS)
print('Current resource limits of RLIMIT_AS (soft/hard): {}/{}'.format(cur_soft, cur_hard))
# Retry: allocate an increasing amount of data.
for val in sz:
stmt = "Allocate %s MB " % val
try:
print("virtual memory: %d MB" % int(p.memory_info().vms/MB))
m = np.arange(val*MB/8, dtype="u8")
print(stmt + " Success.")
except:
print(stmt + " Fail.")
raise
Listing for This Example
>>> import psutil
>>> import numpy as np
>>>
>>> # Get the current OS process.
... p = psutil.Process()
>>>
>>> # Get a list of available resources.
... [attr for attr in dir(psutil) if attr[:7] == 'RLIMIT_']
['RLIMIT_AS', 'RLIMIT_CORE', 'RLIMIT_CPU', 'RLIMIT_DATA',
'RLIMIT_FSIZE', 'RLIMIT_LOCKS', 'RLIMIT_MEMLOCK', 'RLIMIT_MSGQUEUE',
'RLIMIT_NICE', 'RLIMIT_NOFILE', 'RLIMIT_NPROC', 'RLIMIT_RSS',
'RLIMIT_RTPRIO', 'RLIMIT_RTTIME', 'RLIMIT_SIGPENDING', 'RLIMIT_STACK']
>>>
>>> # Display the Virtual Memory Size of the current process.
... p.memory_info().vms
413175808
>>>
>>> # Get the process resource limit RLIMIT_AS.
... soft, hard = p.rlimit(psutil.RLIMIT_AS)
>>> print('Original resource limits of RLIMIT_AS (soft/hard): {}/{}'.format(soft, hard))
Original resource limits of RLIMIT_AS (soft/hard): -1/-1
>>>
>>> # Check the constant used to represent the limit for an unlimited resource.
... psutil.RLIM_INFINITY
-1
>>>
>>> # Set the resource RLIMIT_AS (soft, hard) limit to (1GB, 2GB).
... p.rlimit(psutil.RLIMIT_AS, (pow(1024,3)*1, pow(1024,3)*2))
>>>
>>> # Get the current resource limit of RLIMIT_AS.
... cur_soft, cur_hard = p.rlimit(psutil.RLIMIT_AS)
>>> print('Current resource limits of RLIMIT_AS (soft/hard): {}/{}'.format(cur_soft, cur_hard))
Current resource limits of RLIMIT_AS (soft/hard): 1073741824/2147483648
>>>
>>> # Define a list of sizes to be allocated in MB (megabytes).
... sz = [100, 200, 500, 1000]
>>>
>>> # Define a megabyte variable in bytes.
... MB = 1024*1024
>>>
>>> # Allocate an increasing amount of data.
... for val in sz:
... stmt = "Allocate %s MB " % val
... try:
... print("virtual memory: %d MB" % int(p.memory_info().vms/MB))
... m = np.arange(val*MB/8, dtype="u8")
... print(stmt + " Success.")
... except:
... print(stmt + " Fail.")
... raise
...
virtual memory: 394 MB
Allocate 100 MB Success.
virtual memory: 494 MB
Allocate 200 MB Success.
virtual memory: 594 MB
Allocate 500 MB Fail.
Traceback (most recent call last):
File "<stdin>", line 6, in <module>
MemoryError
>>>
>>> # Delete the allocated variable.
... del m
>>>
>>> # Raise the soft limit of RLIMIT_AS to 2GB.
... p.rlimit(psutil.RLIMIT_AS, (pow(1024,3)*2, pow(1024,3)*2))
>>>
>>> # Get the current resource limit of RLIMIT_AS.
... cur_soft, cur_hard = p.rlimit(psutil.RLIMIT_AS)
>>> print('Current resource limits of RLIMIT_AS (soft/hard): {}/{}'.format(cur_soft, cur_hard))
Current resource limits of RLIMIT_AS (soft/hard): 2147483648/2147483648
>>>
>>> # Retry: allocate an increasing amount of data.
... for val in sz:
... stmt = "Allocate %s MB " % val
... try:
... print("virtual memory: %d MB" % int(p.memory_info().vms/MB))
... m = np.arange(val*MB/8, dtype="u8")
... print(stmt + " Success.")
... except:
... print(stmt + " Fail.")
... raise
...
virtual memory: 458 MB
Allocate 100 MB Success.
virtual memory: 558 MB
Allocate 200 MB Success.
virtual memory: 658 MB
Allocate 500 MB Success.
virtual memory: 958 MB
Allocate 1000 MB Success.