jc.jang

파이썬 메모리 이모저모 - 프로그라피 알고리즘 스터디 개인 발표 자료 본문

개발/행사 후기

파이썬 메모리 이모저모 - 프로그라피 알고리즘 스터디 개인 발표 자료

jangstory 2020. 2. 1. 20:56

변수

  • 특정 메모리 주소를 담음, 메모리 주소에 붙이는 라벨

id함수

  • 해당 객체/변수의 메모리 주소 값을 반환
  • C/C++의 & 포인터 연산자와 동일

is==의 차이점


>>> a = 1000
>>> b = 1000
>>> a is b
False
>>> a == b
True

>>> a = 1000
>>> b = a
>>> a is b
True
>>> a == b
True
  • ==에 비해 is가 약간 더 빠르다. is는 메모리 주소만 비교하지만 ==은 메모리 주소에 저장된 값을 비교한다.

자료형

  • mutable vs immutable

mutable

  • 변경 가능한 객체
  • 객체 값 변경 시 메모리 재할당 없음
  • set, list, dictionary

>>> mutable1 = ['alpha']
>>> hex(id(mutable1))
'0xc44a80'
>>> mutable1.append('bravo')
>>> hex(id(mutable1))
'0xc44a80' # same!

immutable

  • 변경 불가능한 객체
  • 객체 값 변경 시 메모리 재할당
  • int, string

>>> immutable1 = 1000 #int
>>> hex(id(immutable1))
'0x1cddce0'
>>> immutable1 += 1
>>> hex(id(immutable1))
'0x1cdde30'

주의사항


>>> a = 1000
>>> b = a
>>> b += 1
>>> a, b, a is b
결과확인

(1000, 1001, False)


>>> a = ['mon', 'tue']
>>> b = a
>>> b.append('wed')
>>> a, b, a is b
결과확인

['mon', 'tue', 'wed'], ['mon', 'tue', 'wed'], True


>>> a = ['mon', 'tue']
>>> b = a[:]    # for only list
>>> b.append('wed')
>>> a, b, a is b
결과확인

['mon', 'tue'], ['mon', 'tue', 'wed'], False


>>> a = ['mon', 'tue']
>>> b = a.copy()    # for dict, list, set
>>> b.append('wed')
>>> a, b, a is b
결과확인

['mon', 'tue'], ['mon', 'tue', 'wed'], False


>>> a = ['head', ['sub']]
>>> b = a.copy()
>>> b[1].append('sub2')
>>> a, b
결과확인

['head', ['sub', 'sub2']], ['head', ['sub', 'sub2']]

copy.copy()

  • 해당 객체만 메모리를 새로 할당
  • 하위 객체들은 메모리 주소 유지
  • [:]이나 .copy()등과 같은 기능

>>> import copy
>>> a = ['head', ['sub']]
>>> b = copy.deepcopy(a)
>>> b[1].append('sub2')
>>> a, b
결과확인

['head', ['sub']], ['head', ['sub', 'sub2']]

copy.deepcopy()

  • 해당 객체와 하위 객체들의 메모리를 새로 할당
  • 완전히 새로운 객체를 만듦

copy.copy()와 copy.deepcopy()의 차이점


>>> import copy
>>> a = ['head', ['sub']]
>>> b = copy.deepcopy(a)
>>> id(a[1]), id(b[1])
(49520968, 49521208)
>>> c = ['head', ['sub']]
>>> d = c.copy()
>>> id(c[1]), id(d[1])
(50202464, 50202464)

Singleton

  • 모든 인스턴스에서 동일한 메모리 주소 공유
  • 실행중인 파이썬 인스턴스가 없을 경우 재할당
  • True, False, None, Ellipsis, Notimplemented

따라서 특정 객체가 None인지 비교하기 위해서는 == 보다 is를 사용하는것이 더 빠르고 확실하다.

String interning

  • 메모리 최적화를 위해 사용하는 기법 중 하나
  • 문자열을 메모리에 한번만 저장
  • interned string table
  • image binary data 등 용량이 큰 데이터 처리에 유용함

>>> c = 'idolm@ster'  
>>> d = 'idolm@ster'  
>>> c is d  
>>> False  
>>> import sys  
>>> e = sys.intern('idolm@ster')  
>>> f = sys.intern('idolm@ster')  
>>> e is f  
>>> True

필요없는 메모리 값 지우기

'del' keyword

  • 변수를 명시적으로 제거
  • 변수의 선언을 취소

>>> a = 1000
>>> a
1000
>>> del a
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

Reference count

  • 특정 메모리 주소를 참조하는 곳의 수
  • 0이 될 경우 다음 GC때 메모리에서 해제

>>> import sys
>>> a = {'python', 'swift'}
>>> b = a
>>> sys.getrefcount(a)
3

Garbage Collection

  • 필요없는 메모리는 자동으로 해제
  • Generation으로 나눠서 관리
  • 특정 threshold가 존재
  • 가장 낮은 Generation부터 GC (가장 최근에 할당된 변수가 먼저 쓸모 없어지는 경우가 많기 때문이다.)

----------threshold를 3으로 설정----------
----------변수 a----------
----------변수 b----------
----------변수 c----------
----------변수 d, threshold 초과----------
----------collect----------
----------generation 이동----------
----------변수 b 삭제, 변수 e----------
----------변수 f----------
----------threshold 초과----------

 

----------threshold 초과, collect 실행----------
----------변수 g----------

참고 자료

Comments