Утечка памяти при распахивании панд / numpy в Python 3 - PullRequest
0 голосов
/ 27 марта 2020

Я столкнулся с утечкой памяти и не могу отладить ее. Первая часть описывает, что происходит, когда я генерирую данные примера во время выполнения, вторая - когда данные образца кэшируются в файле.

1) Когда я открываю коллекцию (в этом примере dict) pandas (версия 1.0) dataframes, внутри функции возникает утечка памяти. Использование памяти увеличивается с 131 МБ в начале до 2075 в конце (см. Первую и последнюю строку на скриншоте) даже после вызова g c .collect (). Код показан ниже. Снимок экрана дополнительно показывает вывод tracemalloc.

enter image description here

Поскольку это выполняется внутри функции, я ожидал, что все локальные переменные будут очищены при возврате. Интересно, что когда я del данные внутри функции, проблема исчезает для случая, когда я генерирую данные образца внутри функции.

enter image description here

def print_process_mem_usage(do_print=True):
    import os
    import psutil
    process = psutil.Process(os.getpid())
    mem_usg = process.memory_info().rss/1.e6
    if do_print:
        print(f'{mem_usg:3,.0f} MB')
    else:
        return mem_usg


def func():
    import pandas as pd
    import pickle
    df = pd.DataFrame(pd.util.testing.getTimeSeriesData(nper=60_000))
    data = {ix: df.copy() for ix in range(1000)}
    stream = pickle.dumps(data)
    # del data

    print_process_mem_usage()
    out = pickle.loads(stream)
    return out

def trace_memory(func):
    import tracemalloc
    import gc
    tracemalloc.start()
    print_process_mem_usage()
    out = func()
    snapshot1 = tracemalloc.take_snapshot()
    del out
    print_process_mem_usage()
    snapshot2 = tracemalloc.take_snapshot()
    tracemalloc.stop()
    gc.collect()
    print('snapshot 1')
    for stat in snapshot1.statistics('lineno')[:10]:
        print(stat)
    print('snapshot 2')
    for stat in snapshot2.statistics('lineno')[:10]:
        print(stat)
    print_process_mem_usage()

2) Еще хуже, когда я записываю данные в файл, например

def write_sample_data_to_file():
    with open('/tmp/output1', 'wb') as f:
        import pickle
        import numpy as np
        import pandas as pd
        df = pd.DataFrame(pd.util.testing.getTimeSeriesData(nper=60_000))
        stream = {ix: df.copy() for ix in range(1000)}
        stream = pickle.dumps(stream)
        f.write(stream)

write_sample_data_to_file()

, а затем вызовите trace_memory для следующей функции загрузчика:

def func():
    with open('/tmp/output1', 'rb') as f:
        stream = f.read()

    print_process_mem_usage()
    import pickle
    out = pickle.loads(stream)
    del stream

    return out

Даже если я удаляю stream в этой функции, память не освобождается надежно. Повторный вызов функции (иногда для этого также требуется перезапуск ядра) в конечном итоге снова возвращает проблему (около 2 ГБ дополнительного использования памяти).

Любые идеи о том, что происходит или как дальше отследить проблему ?

...