[python] 일반방식 VS 이터레이터 방식
파이썬의 메모리 구조는 그림과 같다.
- 스택(stack) 영역 : 지역변수/매개변수 저장, 함수가 호출될 때 할당되고 호출이 끝나면 소멸
- 힙(heap) 영역 : new명령으로 생성된 인스턴스 변수(사용자의 동적할당)가 저장, 메소드 호출이 끝나도 소멸되지 않음
- 데이터(data) 영역 : 전역변수/정적변수 저장, 프로그램이 시작될때 할당되고 프로그램이 종료되면 소멸
- 코드(text) 영역 : 실행할 프로그램의 코드가 저장
* 파이썬은 메모리를 잘 관리해야 한다. 이러한 이유로 제너레이터와 이터레이터가 있다.
만약 연속된 숫자를 미리 만들면 숫자가 적을 때는 상관없지만 숫자가 많을 때는 메모리를 많이 사용하게 되므로 성능저하가 있을 것이다. 그래서 파이썬에서는 이터레이터만 생성하고 값이 필요한 시점이 되었을 때 값을 만드는 방식을 사용할 수 있다.
그렇다면 일반 방식와 이터레이터를 사용한 방식의 메모리사용량의 차이는 얼마나 있을지 알아보자?
주피터 노트북에서 코드를 짜서 확인해 보겠다.
from memory_profiler import profile
주피터 노트북에서 메모리 사용량을 확인하기 위해서는 라이브러리를 가져와야 한다.
pip install memory-profiler
%load_ext memory_profiler
주피터노트북에서는 위 로드 처리 해야 한다.
### 이터레이터 클래스 생성하기
class SimpleIterator:
def __init__(self, limit):
### 반복 범위를 저정할 값
self.limit = limit
### 반복 시작값
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.limit:
self.current += 1
return self.current
else:
raise StopIteration
### 데코레이터 함수 정의하기
@profile
def no_iterator(limit):
data = [i for i in range(1, limit+1)]
### 이터레이터를 사용해서 메모리 체크하기
@profile
def yes_iterator(limit):
data = SimpleIterator(limit)
for item in data:
### 반복만처리하고 별도 출력은 안함
pass
limit = 1000000
try:
%memit no_iterator(limit)
%memit yes_iterator(limit)
except:
pass
결과 :
ERROR: Could not find file C:\Users\Administrator\AppData\Local\Temp\ipykernel_11360\2777270855.py
peak memory: 111.57 MiB, increment: 38.77 MiB
ERROR: Could not find file C:\Users\Administrator\AppData\Local\Temp\ipykernel_11360\2777270855.py
peak memory: 73.91 MiB, increment: 0.00 MiB
일반적인 방식을 사용할 때에는 peak와 increment값 모두 높은 수치를 나타낸다.
특히 이터레이터를 사용하면 increment값은 전혀 사용하지 않고 있다.
이러한 이유들로 처리할 데이터가 많아지게 되면 일반적인 방식보다는 이터레이터를 사용한다.