2013-03-21 3 views
6

파이썬 세트 모음을 사용하여 고유 한 객체를 저장합니다. 모든 개체에는 __hash____eq__이 재 지정됩니다.파이썬 매우 큰 세트. 메모리 예외를 피하는 방법은 무엇입니까?

약 200,000 개의 물체가 포함되어 있습니다. 세트 자체에는 4GB의 메모리가 필요합니다. 5GB가 넘는 컴퓨터에서 정상적으로 작동하지만 3GB의 RAM 만 사용할 수있는 컴퓨터에서 스크립트를 실행할 필요가 있습니다.

실제로 동일한 소스에서 동일한 데이터를 읽고 set (HashSet)의 CLR 아날로그에 넣고 4GB 대신 350MB 가까이 가져 갔지만 스크립트 실행 속도는 비교적 똑같습니다 (40 초 근처)하지만 파이썬을 사용해야합니다.

Q1 : 파이썬에는 "디스크 지속성"세트 또는 다른 해결 방법이 있습니까? 나는 그것이 해시/eq 방법에 사용 된 "키"데이터 만 메모리에 저장할 수 있으며 다른 모든 것은 디스크에 유지 될 수 있다고 생각한다. 또는 파이썬에서 시스템에서 사용할 수있는 것보다 많은 메모리를 사용할 수있는 고유 한 개체 모음을 갖는 다른 해결 방법이있을 수 있습니다.

질문 2 : 실용적인 질문 : 왜 파이썬 세트가 세트에 더 많은 메모리를 사용합니까?

나는 12.10

감사합니다 64 비트 우분투에서 파이썬 2.7.3 표준 사용합니다.

갱신 1 : 은 무엇 스크립트를 수행합니다

  1. 구문 분석 각 (각 JSON이 관련 집계 개체의 컬렉션 직렬화 된 객체로 구성) 반 구조화 된 JSON 문서를 많이 읽기 JSON 문서를 사용하여 주 개체와 집계 된 개체의 개체를 검색합니다. 파싱 ​​된 모든 객체는 집합에 저장됩니다. 집합은 고유 한 객체 만 저장하는 데 사용됩니다. 첫째로 데이터베이스를 사용했지만 데이터베이스의 고유 한 제약 조건은 x100-x1000보다 느립니다. 모든 JSON 문서는 1-8 개의 다른 객체 유형으로 구문 분석됩니다. 각 객체 유형은 메모리에 고유 한 객체 만 저장하도록 자체 세트에 저장됩니다.

  2. 세트에 저장된 모든 데이터는 고유 한 제한 조건으로 관계형 데이터베이스에 저장됩니다. 각 세트는 별도의 데이터베이스 테이블에 저장됩니다.

, 구조화되지 않은 데이터를 취하는 JSON 문서에서 집계 된 개체 컬렉션에서 중복을 제거하고 관계형 데이터베이스에 구조화 된 데이터를 저장하는 스크립트의 모든 생각.

업데이트 2 :

2 delnan : 나는 같은 (구문 분석, 점점 데이터 반복) 다른 모든 직원을 유지 다른 세트에 추가하는 코드의 모든 라인을 주석 - 스크립트는 4기가바이트 메모리를 적게했다.

200K 개체가 세트에 추가 될 때 이는 많은 메모리를 사용하기 시작한다는 것을 의미합니다. 객체는 TMDB-ID의 단순한 영화 데이터, 장르 목록, 배우 목록, 감독, 기타 많은 영화 세부 정보 및 위키 피 디아의 대형 영화 설명 일 수 있습니다.

+3

왜 데이터베이스를 사용하지 않습니까? –

+0

개체에 어떤 유형의 데이터가 들어 있습니까? 몇 가지 코드를 게시 할 수 있습니까? – TAS

+1

해시를 키로 사용하여 [shelve] (http://docs.python.org/library/shelve.html)에 저장할 수 있습니다. – georg

답변

4

설정이 참 많은 메모리를 사용을하지만, 목록은하지 않습니다.

>>> from sys import getsizeof 
>>> a = range(100) 
>>> b = set(a) 
>>> getsizeof(a) 
872 
>>> getsizeof(b) 
8424 
>>> 

집합을 사용하는 유일한 이유는 중복을 방지하는 것이므로 대신 목록을 사용하는 것이 좋습니다. 객체를 추가하기 전에 목록에 객체가 있는지 테스트하여 중복을 방지 할 수 있습니다. 기본 제공되는 메커니즘을 사용하는 것보다 속도가 느릴 수도 있지만 확실히 적은 메모리를 사용합니다.

2

__slots__을 사용해 메모리 사용량을 줄이십시오.

많은 문제가있는 객체가 많을 때 __slots__을 사용하면 메모리 사용량이 1/3로 줄어 듭니다.

여기는 SO question about __slots__입니다. 흥미로운 부분이 있습니다.

5

아마도 가장 좋은 방법은 세트에 저장하려는 오브젝트를 작게 만드는 것입니다. 불필요한 필드가 있으면 제거하십시오.

당신은 또한 사용 된 필드를 선언하는 __slots__를 사용할 수있는 일반 객체의 오버 헤드를 줄이기 위해 :

class Person(object): 
    __slots__ = ['name', 'age'] 
    def __init__(self): 
     self.name = 'jack' 
     self.age = 99 
+0

CPython을 가정합니다. PyPy는'__slots__' IIRC를 지정하지 않고도 대부분의 객체를 비슷한 방식으로 최적화합니다. – delnan

관련 문제