Почему назначение фрагмента списка питона пожирает память? - PullRequest
6 голосов
/ 30 июля 2010

Я борюсь с утечкой памяти в проекте Python и уже потратил на это много времени.Я вывел проблему на небольшой пример.Теперь кажется, что я знаю решение, но я не могу понять , почему .

import random

def main():
    d = {}
    used_keys = []
    n = 0
    while True:
        # choose a key unique enough among used previously
        key = random.randint(0, 2 ** 60)
        d[key] = 1234 # the value doesn't matter
        used_keys.append(key)
        n += 1
        if n % 1000 == 0:
            # clean up every 1000 iterations
            print 'thousand'
            for key in used_keys:
                del d[key]
                used_keys[:] = []
                #used_keys = []

if __name__ == '__main__':
    main()

Идея состоит в том, что я сохраняю некоторые значения в dict d и запоминаю используемые ключи всписок, чтобы можно было время от времени очищать голос.

Этот вариант программы уверенно пожирает память, никогда не возвращая ее обратно.Если я использую альтернативный метод для «очистки» used_keys, который прокомментирован в примере, все в порядке: потребление памяти остается на постоянном уровне.

Почему?

Протестировано на CPython и многих linux.

Ответы [ 2 ]

5 голосов
/ 30 июля 2010

Вот причина - текущий метод не удаляет ключи из dict (фактически, только один). Это связано с тем, что вы очищаете список used_keys во время цикла, и цикл преждевременно завершается.

Второй (закомментированный) метод, однако, работает, когда вы присваиваете новое значение used_keys, поэтому цикл успешно завершается.

См. Разницу между:

>>> a=[1,2,3]
>>> for x in a:
...    print x
...    a=[]
...
1
2
3

и

>>> a=[1,2,3]
>>> for x in a:
...    print x
...    a[:] = []
...
1
>>>
0 голосов
/ 30 июля 2010

Почему бы что-то не понравится этой работе?

from itertools import count
import uuid

def main():
    d = {}
    for n in count(1):
        # choose a key unique enough among used previously
        key = uuid.uuid1()
        d[key] = 1234 # the value doesn't matter
        if n % 1000 == 0:
            # clean up every 1000 iterations
            print 'thousand'
            d.clear()

if __name__ == '__main__':
    main()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...