2013-08-07 2 views
3

Наша игровая программа инициализирует данные всех игроков в память. Моя цель - уменьшить память, которая не нужна. Я проследил программу и обнаружил, что «для» занимает много памяти.Как я могу освободить память, вызванную «за»

Например:

Line # Mem usage Increment Line Contents 
================================================ 
    52        @profile 
    53 11.691 MB  0.000 MB def test(): 
    54 19.336 MB  7.645 MB  a = ["1"] * (10 ** 6) 
    55 19.359 MB  0.023 MB  print recipe.total_size(a, verbose=False) 
    56 82.016 MB 62.656 MB  for i in a: 
    57          pass 

печати recipe.total_size (а, многословен = False): 8000098 байт

Вопрос заключается в том, как я могу выпустить что 62.656 Мб памяти.

P.S.

К сожалению, я знаю, что мой английский не очень well.I по достоинству оценят все, чтобы прочитать это :-)

+5

Я боюсь, что ваш анализ здесь неверен. Все 'for' does - это создать объект-итератор для' a', который является не чем иным, как ссылкой на 'a' и значением индекса для отслеживания того, где находится список, в котором находится итератор. ** Нет ничего более **. –

+0

Какой инструмент я использовал memory_profiler.Хотя я не совсем понимаю его, он приветствуется в github. (Https://github.com/fabianp/memory_profiler) Если «for» больше не делал, где фигура (62.656 МБ)? – wangbuze

+0

Я предполагаю, что здесь должен быть виноват список 'a'; на моем 64-битном Mac список с 1 миллионом строк занимает около 44 МБ памяти; 7MB, как сообщается, недостаточно даже для 32-битной системы. Я вычислил этот размер с помощью функции 'sys.getsizeof()' для измерения требований к памяти одной строки '' 1 '', умноженной на 1 миллион, плюс размер объекта списка с 1 миллионом ссылок. –

ответ

0

Если вы абсолютно отчаянный, чтобы уменьшить использование памяти на петле вы можете сделать это следующим образом:.

i = 0 
while 1: 
    try: 
     a[i] #accessing an element here 
     i += 1 
    except IndexError: 
     break 

статистика памяти (если они являются точными):

12  9.215 MB  0.000 MB  i = 0 
13  9.215 MB  0.000 MB  while 1: 
14 60.484 MB 51.270 MB   try: 
15 60.484 MB  0.000 MB    a[i] 
16 60.484 MB  0.000 MB    i += 1 
17 60.484 MB  0.000 MB   except IndexError: 
18 60.484 MB  0.000 MB    break 

Однако этот код выглядит некрасиво и опасность и уменьшение использования памяти только крошечные.

+0

Зачем вам делать этот диапазон, чем 'for i в диапазоне (...)'? –

+0

xrange дает значения вместо сохранения их в памяти. Поэтому в случае больших последовательностей может помочь сэкономить память.Однако, к сожалению, в этом конкретном случае кажется, что это не помогло, возможно потому, что оно дает только целые числа. И именно поэтому я изменил свое решение на лучшее, но только с точки зрения использования памяти. – Lukasz

+0

@jentyk: Вы сделали хорошо. Вы действительно уменьшите использование памяти. Но я не могу использовать его в своем проекте, вы знаете, почему. :-) Я ожидаю лучшей идеи. – wangbuze

0

1) Вместо list iterator. Вы должны использовать generator. в соответствии с вашим образцом кода:

@profile 
def test(): 
    a = ("1" for i in range(10**6)) #this will return a generator, instead of a list. 
    for i in a: 
     pass 

Теперь, если вы используете generator 'a' в for loop, он не будет считать, что много памяти.

2) Если вы получаете list, сначала конвертируйте его в generator.

@profile 
def test(): 
    a = ["1"] * (10**6) #getting list 
    g = (i for i in a) #converting list into a generator object 
    for i in g:   #use generator object for iteration 
     pass 

Попробуйте это. Если вам помогает.

+0

Спасибо, но в моей реальной программе результат запроса вместо списка «a» .Twisted dbapi возвращает его. Он не может быть преобразован в генератор. Это делает меня безумным. – wangbuze

+0

Я отредактировал свой ответ в соответствии. Посмотрите, если это сработает. –

+0

1) Он действительно работал в этом демонстрационном тесте. Но в моей игровой программе «a» - результат запроса из db.It - это список. – wangbuze

Смежные вопросы