Python 3.7.4 -> Как сохранить низкое потребление памяти? - PullRequest
1 голос
/ 10 февраля 2020

Следующий код извлекает, создает и индексирует uniqueCards для данной базы данных.

for x in range(2010,2015):
    for y in range(1,13):
        index = str(x)+"-"+str("0"+str(y) if y<10 else y)
        url = urlBase.replace("INDEX",index)
        response  = requests.post(url,data=query,auth=(user,pwd))

        if response.status_code != 200:
            continue

        #this is a big json, around 4MB each
        parsedJson = json.loads(response.content)["aggregations"]["uniqCards"]["buckets"]

        for z in parsedJson:
            valKey = 0
            ind = 0
            header = str(z["key"])[:8]

            if header in headers:
                ind = headers.index(header)
            else:
                headers.append(header)

            valKey = int(str(ind)+str(z["key"])[8:])

            creditCards.append(CreditCard(valKey,x*100+y))

Объект CreditCard, единственный объект, который выживает в области действия, имеет длину около 64 байт каждая.
После запуска этот код должен был отобразить около 10 миллионов карт. Это будет означать 640 миллионов байт или около 640 мегабайт.

Проблема в том, что на полпути этой операции потребление памяти достигает 3 ГБ ...

Мое первое предположение заключается в том, что для почему-то G C не собирает parsedJson. Что я должен делать, чтобы контролировать потребление памяти? Могу ли я избавиться от этого объекта вручную?

Edit1:
Кредитная карта определяется как

class CreditCard:
    number = 0
    knownSince = 0
    def __init__(self, num, date):
        self.number=num
        self.knownSince=date

Edit2:
Когда я получаю 3,5 миллиона карт на creditCards.__len__(), sys.getsizeof(creditCards) сообщает 31 МБ, но процесс занимает 2 ГБ!

1 Ответ

1 голос
/ 11 февраля 2020

проблема в json.load. Загрузка 4 МБ приводит к 5-8-кратному скачку памяти.

Редактировать:

Мне удается обойти эту проблему с помощью пользовательского преобразователя для JSON:

def object_decoder(obj):
    if obj.__contains__('key'):
        return CreditCard(obj['key'],xy)
    return obj

Теперь память растет медленно, и я смог проанализировать весь набор, используя около 2 ГБ памяти

...