대용량 쿼리를 일괄 처리하여 장고 앱의 메모리 사용을 줄이려고합니다. 비록 제가 영리하다고 생각한다고하더라도, 메모리 사용은 결국 프로세스가 죽을 때까지 계속 증가했습니다. 나는 현재 쿼리 세트가 가비지 수집되지 않는다는 이론을 가지고 있으며, 쿼리를 배치하는 방법과 관련이 있는지 궁금해하고 있습니다. itertools.chain()은 소비 된 아이템에서 메모리를 해제 할 수 있습니까?
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
def get_data(pks):
groups = list(grouper(pks, batch_size))
querysets = [_queryset(pks) for pks in groups]
return itertools.chain(*querysets)
for item in get_data([..big list of primary keys..]):
process(item)
는의 3 개 검색어 세트가
get_data
기능에서 발생한다고 가정 해 봅시다. 첫 번째 쿼리 세트의 모든 항목을 소비하면 해당 쿼리 세트가 해제됩니까? 아니면 아직도 체인에서 기술적으로 참조를 얻었습니까?
메모리가 여기에 있습니다 (데이터베이스 드라이버 일 수도 있고 장고 자체 내부의 뭔가 일 수도 있음).하지만 괜찮은 후보로 보입니다. 객체 유형별로 메모리 사용을 측정하는 데 유용한 도구가 있습니까? 이 특정 코드는 Python 2에서 실행되고 있습니다 (현재).
필자는 ipython 셸에서이 프로그램을 실행하고 있음을 유의해야한다.
편집 :
그것은 chain
처럼 보이는 여기에 책임을지지 않습니다. 클래스 당 객체 수를 출력하는 코드를 추가하고 Model 객체 수를 일정한 수로 유지합니다.
import gc
def get_object_counts():
from collections import Counter
classes = []
for obj in gc.get_objects():
if hasattr(obj, '__class__'):
classes.append(str(obj.__class__))
return Counter(classes)
그런 다음 특정 간격 (일괄 처리 크기)에서 : 완료 위해서
print(get_object_counts().most_common(30))
, 여기에 상단 9. 나는 주요 원인은 성장 여부를 수집하기 계속 django.db.models.base.ModelState
,이라고 생각합니다.
첫째 :
("<type 'dict'>", 59184)
("<type 'list'>", 48710)
("<type 'function'>", 48300)
("<type 'tuple'>", 38920)
("<type 'cell'>", 10203)
("<type 'weakref'>", 9957)
("<type 'set'>", 7230)
("<type 'type'>", 5947)
("<class 'django.db.models.base.ModelState'>", 4682)
둘째 :
("<type 'dict'>", 59238)
("<type 'list'>", 48730)
("<type 'function'>", 48315)
("<type 'tuple'>", 38937)
("<type 'cell'>", 10207)
("<type 'weakref'>", 9959)
("<type 'set'>", 7230)
("<type 'type'>", 5950)
("<class 'django.db.models.base.ModelState'>", 4696)
고마워, 그게 정말 도움이되는 정보 야. 다른 발전기의 체인에 인수를 래핑 멋진 트릭. 원래 코드를 리팩토링하여 실제로 테스트 할 수 없게되었지만 충분히 질문에 답한 것 같습니다. –