Python 객체의 메모리 크기 구하는 방법

mhComa·2023년 2월 18일
1
import sys
sys.getsizeof(obj)

sys 모듈의 getsizeof 함수로 오브젝트의 크기를 구할 수 있다.
int 타입의 값을 반환하고,
그 값은 메모리 상에서 차지하는 바이트 수를 의미한다.

https://docs.python.org/3/library/sys.html#sys.getsizeof

크기는 하드웨어와 버전, 구현체에 따라 다를 수 있다.


64비트 윈도의 파이썬3 기준으로,
어떤 결과가 나오는 지 주석으로 적었다.

print(sys.getsizeof(None))      # 16
print(sys.getsizeof(object()))  # 16

파이썬의 내장 객체는 기본적으로
가비지 컬렉션을 위한 ssize_t (64비트이므로 8바이트) 레퍼런스 카운트와,
타입 정보에 대한 포인터 (64비트이므로 8바이트)로 구성되어 있다.


print(sys.getsizeof(0))         # 24
print(sys.getsizeof(1))         # 28
print(sys.getsizeof(2 ** 30))   # 32
print(sys.getsizeof(2 ** 60))   # 36
print(sys.getsizeof(-1))        # 28

파이썬에서 정수는 임의 정밀도(Arbitrary-precision, Bignum) 방식이기 때문에
숫자가 증가할 수록 크기가 늘어난다.

https://rushter.com/blog/python-integer-implementation/

레이아웃을 알아보니 정수는
레퍼런스 카운트와 타입 정보에 대한 포인터,
int가 임의 정밀도이기 위해 필요한 ssize_t 크기 정보,
각 수를 나타내는 uint32_t[] digit 데이터 로 구성되어있다.

print(sys.int_info)
# sys.int_info(bits_per_digit=30, sizeof_digit=4, default_max_str_digits=4300, str_digits_check_threshold=64

2의 30승마다 증가하고 digit 크기는 4바이트임을 알 수 있다.
0은 크기가 없는 상태다. 그러므로 24바이트.


print(sys.getsizeof(False))     # 24
print(sys.getsizeof(True))      # 28

TrueFalse보다 4바이트 많다.
파이썬에서 bool은 int의 서브클래스로 구현됐기 때문이다.

https://docs.python.org/3/c-api/bool.html


print(sys.getsizeof(0.0))    # 24
print(sys.getsizeof(1.0))    # 24

float는 IEEE 754를 그대로 사용한다.
기본적인 오브젝트 구조에 double의 8바이트가 더해져 24바이트로 나왔다.

https://github.com/python/cpython/blob/main/Include/cpython/floatobject.h


print(sys.getsizeof(''))        # 49
print(sys.getsizeof('a'))       # 50
print(sys.getsizeof('aa'))      # 51
print(sys.getsizeof('あ'))      # 76
print(sys.getsizeof('あa'))     # 78

str의 경우,
a가 하나씩 늘어날 때마다 1바이트 늘어나는 건 직관적이지만,
어째서 아스키 문자가 아닌 가 있을 때는 왜 74바이트로 시작하는 것이고,
같은 a가 추가될 때 2바이트씩 늘어나는 지...

이런 현상은 파이썬의 문자열 처리 방식 때문이다.

https://rushter.com/blog/python-strings-and-memory/

는 Latin-1 밖에 있으므로
문자열은 UCS-2 문자열이 되어
한 문자에 2바이트씩 차지하게 된 것이다.
한글도 BMP(Basic Multilingual Plane) 상에 있으므로,
한글이 들어간 문자열도 2바이트씩을 차지하게 된다.

그 외에 왜 빈 문자열이 49바이트인지,
UCS-2 문자열이 74바이트가 기본인지는...
부가 정보가 많아서 그렇다.


그 외 컬렉션이든 변수든 참조를 기반으로 하는 경우가 많아서 더 건질 정보는 딱히 없는 것 같다.
시·공간적 효율 측면에서 표준 라이브러리나 NumPyarray를 사용하는 경우도 있으니 참고.

이렇게 주구장창 적어놓긴 했지만 이걸 알아서 딱히 효율적이게 되진 않을 거라 본다.
애초에 파이썬을 쓸 때 메모리가 걱정이면 파이썬을 안 쓰면 되니까.

profile
Ich bin ein Hund!

0개의 댓글