resource — Gestión de recursos del sistema

Propósito:Gestiona los límites de recursos del sistema para un programa Unix.

Las funciones en resource sondean los recursos actuales del sistema consumidos por un proceso y les ponen límites para controlar cuánta carga puede imponer un programa en un sistema.

Uso actual

Usa getrusage() para sondear los recursos utilizados por el proceso actual y/o sus hijos. El valor de retorno es una estructura de datos que contiene varias métricas de recursos basadas en el estado actual del sistema.

Nota

No todos los valores de recursos recopilados se muestran aquí. Consulta la documentación de la biblioteca estándar de resource para obtener una lista más completa.

resource_getrusage.py
import resource
import time

RESOURCES = [
    ('ru_utime', 'User time'),
    ('ru_stime', 'System time'),
    ('ru_maxrss', 'Max. Resident Set Size'),
    ('ru_ixrss', 'Shared Memory Size'),
    ('ru_idrss', 'Unshared Memory Size'),
    ('ru_isrss', 'Stack Size'),
    ('ru_inblock', 'Block inputs'),
    ('ru_oublock', 'Block outputs'),
]

usage = resource.getrusage(resource.RUSAGE_SELF)

for name, desc in RESOURCES:
    print('{:<25} ({:<10}) = {}'.format(
        desc, name, getattr(usage, name)))

Debido a que el programa de prueba es extremadamente simple, no utiliza muchos recursos.

$ python3 resource_getrusage.py

User time                 (ru_utime  ) = 0.032299999999999995
System time               (ru_stime  ) = 0.01517
Max. Resident Set Size    (ru_maxrss ) = 9945088
Shared Memory Size        (ru_ixrss  ) = 0
Unshared Memory Size      (ru_idrss  ) = 0
Stack Size                (ru_isrss  ) = 0
Block inputs              (ru_inblock) = 0
Block outputs             (ru_oublock) = 0

Límites de recursos

Separado del uso actual actual, es posible verificar los límites impuestos a la aplicación y luego cambiarlos.

resource_getrlimit.py
import resource

LIMITS = [
    ('RLIMIT_CORE', 'core file size'),
    ('RLIMIT_CPU', 'CPU time'),
    ('RLIMIT_FSIZE', 'file size'),
    ('RLIMIT_DATA', 'heap size'),
    ('RLIMIT_STACK', 'stack size'),
    ('RLIMIT_RSS', 'resident set size'),
    ('RLIMIT_NPROC', 'number of processes'),
    ('RLIMIT_NOFILE', 'number of open files'),
    ('RLIMIT_MEMLOCK', 'lockable memory address'),
]

print('Resource limits (soft/hard):')
for name, desc in LIMITS:
    limit_num = getattr(resource, name)
    soft, hard = resource.getrlimit(limit_num)
    print('{:<23} {}/{}'.format(desc, soft, hard))

El valor de retorno para cada límite es una tupla que contiene el límite suave impuesto por la configuración actual y el límite duro impuesto por el sistema operativo.

$ python3 resource_getrlimit.py

Resource limits (soft/hard):
core file size          0/9223372036854775807
CPU time                9223372036854775807/9223372036854775807
file size               9223372036854775807/9223372036854775807
heap size               9223372036854775807/9223372036854775807
stack size              8388608/67104768
resident set size       9223372036854775807/9223372036854775807
number of processes     1418/2128
number of open files    9472/9223372036854775807
lockable memory address 9223372036854775807/9223372036854775807

Los límites se pueden cambiar con setrlimit().

resource_setrlimit_nofile.py
import resource
import os

soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
print('Soft limit starts as  :', soft)

resource.setrlimit(resource.RLIMIT_NOFILE, (4, hard))

soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
print('Soft limit changed to :', soft)

random = open('/dev/random', 'r')
print('random has fd =', random.fileno())
try:
    null = open('/dev/null', 'w')
except IOError as err:
    print(err)
else:
    print('null has fd =', null.fileno())

Este ejemplo usa RLIMIT_NOFILE para controlar la cantidad de archivos abiertos permitidos, cambiándolo a un límite suave más pequeño que el predeterminado.

$ python3 resource_setrlimit_nofile.py

Soft limit starts as  : 9472
Soft limit changed to : 4
random has fd = 3
[Errno 24] Too many open files: '/dev/null'

También puede ser útil limitar la cantidad de tiempo de CPU que un proceso debería consumir, para evitar usar demasiado. Cuando el proceso pasa el tiempo asignado, envía una señal SIGXCPU.

resource_setrlimit_cpu.py
import resource
import sys
import signal
import time


# Set up a signal handler to notify us
# when we run out of time.
def time_expired(n, stack):
    print('EXPIRED :', time.ctime())
    raise SystemExit('(time ran out)')


signal.signal(signal.SIGXCPU, time_expired)

# Adjust the CPU time limit
soft, hard = resource.getrlimit(resource.RLIMIT_CPU)
print('Soft limit starts as  :', soft)

resource.setrlimit(resource.RLIMIT_CPU, (1, hard))

soft, hard = resource.getrlimit(resource.RLIMIT_CPU)
print('Soft limit changed to :', soft)
print()

# Consume some CPU time in a pointless exercise
print('Starting:', time.ctime())
for i in range(200000):
    for i in range(200000):
        v = i * i

# We should never make it this far
print('Exiting :', time.ctime())

Normalmente, el controlador de señal debe vaciar todos los archivos abiertos y cerrarlos, pero en este caso solo imprime un mensaje y sale.

$ python3 resource_setrlimit_cpu.py

Soft limit starts as  : 9223372036854775807
Soft limit changed to : 1

Starting: Sun Mar 18 16:21:52 2018
EXPIRED : Sun Mar 18 16:21:53 2018
(time ran out)

Ver también