배경
특정 API를 호출시 계속 서버의 메모리가 폭증하는 현상 발생
-> loop 혹은 DB 데이터가 Python 메모리로 불러오는 과정에서 문제가 있을 것으로 생각하고 프로파일링을 통해 원인을 찾아 보기로 하였다.
결과적으로 API에서 비효율적으로 파이썬 메모리를 사용하는 로직을 찾아 수정하여서 해결하였다.
memory_profiler 외부 패키지 라이브러리
메모리를 개괄적으로 프로파일링 할 수 있는 외부 패키지 라이브러리
docs 링크 : https://pypi.org/project/memory-profiler/
패키지 설치
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()
결과
다음과 같이 한 row 별로 메모리 사용량 | 증감량 | 빈도 수 등을 나타내 준다.