카테고리 없음

[Utils] Python 메모리 프로파일러 (memory_profiler)

yubi5050 2024. 5. 5. 19:08

배경

특정 API를 호출시 계속 서버의 메모리가 폭증하는 현상 발생

-> loop 혹은 DB 데이터가 Python 메모리로 불러오는 과정에서 문제가 있을 것으로 생각하고 프로파일링을 통해 원인을 찾아 보기로 하였다.

 

결과적으로 API에서 비효율적으로 파이썬 메모리를 사용하는 로직을 찾아 수정하여서 해결하였다.

 

memory_profiler  외부 패키지 라이브러리

메모리를 개괄적으로 프로파일링 할 수 있는 외부 패키지 라이브러리

docs 링크 : https://pypi.org/project/memory-profiler/

 

memoy-profiler

A module for monitoring memory usage of a python program

pypi.org

 

패키지 설치

pip install memory_profiler

 

 

예시 코드

profile 함수는 데코레이터 형태로 제공되기 떄문에, 추적을 원하는 부분이 함수 화 되어 있으면 좋다.

  • [1, 2, 3 ... ] : 각각의 원소 들은 포인터 위치 저장 메모리를 가진다.
  • [0] * 100000 : 각각의 원소 들은 동일한 포인터 위치 저장 메모리를 참조한다.
  • del [변수명] : 바로 메모리가 반환되지 않는다. (python은 레퍼런스 카운팅이라는 가비지 컬렉션이 있기 때문
  • a.copy() : 얕은 복사 (실제 메모리 주소가 늘어나지 않는다.
  • a.deppcopy() : 깊은 복사 (실제 메모리 주소가 복사되어, 새로운 메모리 주소에 저장된다.)

 

from memory_profiler import profile
import copy 

@profile
def memory_test():
    # a는 0~100,000의 정수를 각각에 대한 메모리 공간을 할당
    a = []
    for i in range(100000):
        a.append(i)

    # 원소 0의 10만개 리스트
    b = [0] * 100000
    del b                   # python의 가비지 컬렉션에 의해 지우더라도 모메리가 바로 반환 되지 않음.

    # 얕은복사 깊은 복사
    c = a.copy()            # 메모리 증가 x
    d = copy.deepcopy()     # 메모리 증가 o 


if __name__ == '__main__':
    memory_test()

 

  1.  

결과

다음과 같이 한 row 별로 메모리 사용량 | 증감량 | 빈도 수 등을 나타내 준다.