Python의 모든 클래스는 인스턴스 속성(instance attribute)을 가집니다. 기본적으로, 이러한 객체의 인스턴스 속성을 관리하기 위해 Python에서 내부적으로 딕셔너리를 사용합니다. 객체의 __dict__ 필드에 접근하여 인스턴스 속성들을 딕셔너리 형태로 확인할 수 있고, 이는 런타임에 새로운 속성을 설정하는 데에 매우 유용하게 사용됩니다.

그러나, 알려진(known) 속성들로 구성된 클래스들의 경우 이러한 구조는 딕셔너리가 낭비하는 RAM 때문에 병목이 발생할 수 있습니다. 클래스 레벨에 __slots__라는 변수를 설정해서, 해당 클래스에 의해 만들어진 객체의 인스턴스 속성 관리에 딕셔너리 대신 속성에 대한 고정된(fixed) set을 사용하도록 할 수 있습니다.

__slots__가 정의된 클래스의 인스턴스에는 __dict__ 필드가 없다 정도밖에 차이가 없어 보이지만, IronPython의 도움을 받아 메모리 사용량을 보면, 효율이 확실히 개선된 것을 확인할 수 있습니다. ipython-memory-usage를 사용해, 1024 * 256개의 객체 생성에 대한 메모리 사용량을 확인해 보았습니다.

In [1]: class WithoutSlots:
   ...:     def __init__(self, name, identifier):
   ...:         self.name = name
   ...:         self.identifier = identifier
   ...:

In [2]: class WithSlots:
   ...:     __slots__ = ['name', 'identifier']
   ...:     def __init__(self, name, identifier):
   ...:         self.name = name
   ...:         self.identifier = identifier
   ...:

In [3]: import ipython_memory_usage.ipython_memory_usage as imu

In [4]: size = 1024 * 256

In [5]: imu.start_watching_memory()
In [5] used 0.0000 MiB RAM in 5.31s, peaked 0.00 MiB above current, total RAM usage 15.57 MiB

In [6]: x = [WithoutSlots(1, 1) for _ in range(size)]
In [6] used 22.6680 MiB RAM in 0.80s, peaked 0.00 MiB above current, total RAM usage 38.24 MiB

In [7]: x = [WithSlots(1, 1) for _ in range(size)]
In [7] used 9.3008 MiB RAM in 0.72s, peaked 0.00 MiB above current, total RAM usage 47.54 MiB


'Python 계열 > Python 레거시 글' 카테고리의 다른 글

requirements.txt로 협업 상황에서의 의존성 관리하기  (0) 2018.11.07
pip  (0) 2018.11.05
Context Manager  (0) 2018.11.01
Argument Unpacking  (0) 2018.10.30
[Python] zip  (0) 2018.07.28

+ Recent posts