Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python resource 모듈로 리소스 사용량 측정과 제한하는 방법

UNIX 환경에서 프로그램의 리소스 사용량을 측정하고 제어하려면 Python의 resource 모듈을 활용할 수 있습니다. 이 모듈은 현재 프로세스가 사용한 CPU 시간, 메모리 등의 시스템 자원 정보를 조회하는 기능과 함께, 프로세스가 소비할 수 있는 자원의 상한선을 설정하는 기능도 제공합니다.

모듈을 사용하려면 먼저 다음과 같이 임포트합니다.

import resource

리소스 제한(Resource Limits)

resource 모듈에서는 setrlimit() 함수를 사용해 프로세스의 자원 사용량에 제한을 둘 수 있습니다. 이때 두 가지 매개변수가 사용되는데, 바로 소프트 리밋(soft limit)하드 리밋(hard limit)입니다.

  • 소프트 리밋: 현재 적용 중인 실질적인 제한값으로, 프로세스 실행 중 변경할 수 있지만 하드 리밋을 초과할 수는 없습니다.
  • 하드 리밋: 소프트 리밋이 넘을 수 없는 상한선으로, 더 낮은 값(소프트 리밋 이상)으로는 줄일 수 있지만 다시 올릴 수는 없습니다.

리소스 제한과 관련된 주요 메서드는 다음과 같습니다.

resource.getrlimit(resource)

지정한 자원의 소프트 리밋과 하드 리밋을 튜플 형태로 반환합니다. 유효하지 않은 자원을 지정하면 ValueError 예외가 발생합니다.

resource.setrlimit(resource, limits)

자원에 제한값을 설정합니다. limits는 (소프트 리밋, 하드 리밋) 형태의 튜플로 지정하며, RLIM_INFINITY를 사용하면 해당 자원을 무제한으로 설정할 수 있습니다.

resource.prlimit(pid, resource[, limits])

setrlimit()getrlimit()의 기능을 결합한 메서드로, 임의의 프로세스에 대해 자원 제한을 조회하고 설정하는 작업을 동시에 수행할 수 있습니다. pid가 0이면 현재 프로세스를 대상으로 동작합니다.

리소스 제한 관련 상수

번호상수 및 설명
1

RLIM_INFINITY

무제한 자원을 나타내는 한계값

2

RLIMIT_CORE

현재 프로세스가 생성할 수 있는 코어 파일의 최대 크기

3

RLIMIT_CPU

프로세서가 사용할 수 있는 최대 CPU 시간. 한도를 초과하면 프로세스에 SIGXCPU 시그널이 전달됩니다.

4

RLIMIT_DATA

프로세스 힙(heap) 영역의 최대 크기

5

RLIMIT_STACK

호출 스택(call stack)의 최대 크기. 멀티스레드 프로세스에서는 메인 스레드의 스택에 적용됩니다.

6

RLIMIT_NOFILE

현재 프로세스가 열 수 있는 파일 디스크립터의 최대 개수

7

RLIMIT_MEMLOCK

메모리에 고정(lock)할 수 있는 주소 공간의 최대 크기

8

RLIMIT_NICE

프로세스 nice 레벨의 상한값

9

RLIMIT_SWAP

사용할 수 있는 스왑(swap) 공간의 최대 크기

10

RLIMIT_NPTYS

시스템에서 생성 가능한 의사 터미널(pseudo terminal)의 최대 개수

리소스 사용량(Resource Usage)

자원 사용량을 조회하는 데 사용되는 메서드와 상수도 제공됩니다.

resource.getrusage(who)

현재 프로세스 또는 그 자식 프로세스가 사용한 자원 정보를 담은 객체를 반환합니다. 반환 객체의 각 필드(ru_utime, ru_stime, ru_maxrss 등)를 통해 CPU 사용 시간, 최대 메모리 사용량 등 구체적인 자원 사용 내역을 확인할 수 있습니다.

resource.getpagesize()

시스템 페이지의 크기를 바이트 단위로 반환합니다. 반환값은 물리적 페이지 크기와 다를 수 있습니다.

리소스 사용량 관련 상수

번호상수 및 설명
1

RUSAGE_SELF

호출한 프로세스 자신이 소비한 자원을 요청합니다. 여러 스레드의 자원 사용량이 모두 합산된 값입니다.

2

RUSAGE_CHILDREN

자식 프로세스들이 소비한 자원을 요청합니다.

3

RUSAGE_BOTH

호출한 프로세스와 자식 프로세스가 소비한 자원을 함께 요청합니다. 일부 시스템에서는 지원되지 않습니다.

4

RUSAGE_THREAD

현재 스레드가 사용한 자원을 요청합니다. 일부 시스템에서는 지원되지 않습니다.

예제 코드

아래 예제는 현재 프로세스의 자원 사용 정보를 출력하고, 페이지 크기를 확인한 뒤, CPU 시간 제한을 1초(소프트) / 2초(하드)로 설정한 후 무거운 반복문을 실행하는 코드입니다.

import resource

res_limits = resource.getrusage(resource.RUSAGE_SELF)
print(res_limits)
print('Page Size: ' + str(resource.getpagesize()))

# CPU 시간 제한 설정: (소프트 리밋 1초, 하드 리밋 2초)
resource.setrlimit(resource.RLIMIT_CPU, (1, 2))
print('Resource Limits: ' + str(resource.getrlimit(resource.RLIMIT_CPU)))

for a in range(1000):
    for b in range(1000):
        for c in range(1000):
            pass

실행 결과

$ python3 example.py
resource.struct_rusage(ru_utime=0.035801, ru_stime=0.01074, ru_maxrss=9356, ru_ixrss=0, ru_idrss=0,
ru_isrss=0, ru_minflt=1147, ru_majflt=0, ru_nswap=0, ru_inblock=0, ru_oublock=0,
ru_msgsnd=0, ru_msgrcv=0, ru_nsignals=0, ru_nvcsw=0, ru_nivcsw=17)
Page Size: 4096
Resource Limits: (1, 2)
CPU time limit exceeded (core dumped)

실행 결과를 보면 getrusage()가 반환한 구조체에 사용자 CPU 시간(ru_utime), 시스템 CPU 시간(ru_stime), 최대 상주 메모리(ru_maxrss) 등의 정보가 포함되어 있으며, 페이지 크기는 4096바이트로 확인됩니다. 또한 CPU 시간 제한을 (1, 2)로 설정한 후 반복문이 제한 시간을 초과하여 CPU time limit exceeded 오류와 함께 프로세스가 종료된 것을 알 수 있습니다. 이처럼 resource 모듈을 활용하면 프로세스의 자원 사용 현황을 진단하고, 비정상적인 자원 소비를 사전에 차단할 수 있습니다.