2016-07-03 2 views
0

Резюмепамяти не освобождаются при принятии небольшого кусочка DataFrame

adataframe является DataFrame с 800K строк. Естественно, он потребляет немного памяти. Когда я это делаю:

adataframe = adataframe.tail(144) 

память не отпущена.

Вы можете утверждать, что это выпущено, но, похоже, оно используется, но оно помечено как свободное и будет повторно использоваться Python. Однако, если я попытаюсь создать новый 800k-ряд DataFrame, а также сохранить только небольшой фрагмент, использование памяти будет расти. Если я снова это сделаю, он будет расти снова, до бесконечности.

Я использую Debian Jessie's Python 3.4.2 с Pandas 0.18.1 и numpy 1.11.1.

Демонстрация с минимальной программой

со следующей программой создать словарь

data = { 
    0: a_DataFrame_loaded_from_a_CSV,_only_the_last_144_rows, 
    1: same_thing, 
    # ... 
    9: same_thing, 
} 

и я контролировать использование памяти в то время как я создаю словарь. Вот оно:

#!/usr/bin/env python3 

from resource import getrusage, RUSAGE_SELF 

import pandas as pd 


def print_memory_usage(): 
    print(getrusage(RUSAGE_SELF).ru_maxrss) 


def read_dataframe_from_csv(f): 
    result = pd.read_csv(f, parse_dates=[0], 
         names=('date', 'value', 'flags'), 
         usecols=('date', 'value', 'flags'), 
         index_col=0, header=None, 
         converters={'flags': lambda x: x}) 
    result = result.tail(144) 
    return result 


print_memory_usage() 
data = {} 
for i in range(10): 
    with open('data.csv') as f: 
     data[i] = read_dataframe_from_csv(f) 
    print_memory_usage() 

Результаты

Если data.csv содержит только несколько строк (например, 144, в этом случае нарезка избыточен), использование памяти растет очень медленно. Но если data.csv содержит 800K строк, результаты похожи на эти:

52968 
153388 
178972 
199760 
225312 
244620 
263656 
288300 
309436 
330568 
349660 

(Добавление gc.collect() перед print_memory_usage() не делает существенной разницы.)

Что я могу поделать?

ответ

0

Как заметил @Alex, нарезка кадра данных дает вам только исходный фрейм, но не удаляет его; для этого вам нужно использовать .copy(). Однако, даже когда я использовал .copy(), использование памяти росло и росло и росло, хотя и медленнее.

Я подозреваю, что это связано с тем, как использовать память Python, и pandas. Dataframe не является одним объектом в памяти; он содержит указатели на другие объекты (особенно в данном конкретном случае, на строки, которые являются столбцами «флаги»). Когда фрейм-фрейм освобождается и эти объекты освобождаются, освобожденное свободное пространство памяти может быть фрагментировано. Позже, когда будет создан огромный новый фреймворк, возможно, он не сможет использовать фрагментированное пространство, и может потребоваться выделение нового пространства. Детали зависят от многих мелочей, таких как версии Python, numpy и pandas, а также подробности каждого случая.

Вместо того, чтобы исследовать эти небольшие детали, я решил, что чтение огромного временного ряда, а затем разрезание - это не выход, и что я должен прочитать только ту часть, которая мне нужна с самого начала. Мне нравится часть кода, который я создал для этого, а именно модуль textbisect и класс FilePart.

1

Вы можете утверждать, что он выпущен, но, по-видимому, он используется, но что он отмечен как свободный и будет повторно использоваться Python.

Правильно, так работает maxrss (он измеряет пиковое использование памяти). См. here.

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

Я подозреваю, что это связано с тем, что подмножество возвращает DataFrame, который действует как прокси-сервер для исходного (поэтому значения не нужно копировать). Это приведет к относительно быстрой операции подмножества, но также утечка памяти, подобная той, которую вы нашли, и weird speed characteristics при настройке значений.

+0

Действительно, если я изменяю 'result = result.tail (144)' to 'result = result.tail (144) .copy(); gc.collect() ', он потребляет на 100 М меньше после 10 итераций. Однако он все еще растет, растет и растет, хотя и с меньшими темпами. –

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