Я столкнулся с утечкой памяти и не могу отладить ее. Первая часть описывает, что происходит, когда я генерирую данные примера во время выполнения, вторая - когда данные образца кэшируются в файле.
1) Когда я открываю коллекцию (в этом примере dict
) pandas (версия 1.0) dataframes
, внутри функции возникает утечка памяти. Использование памяти увеличивается с 131 МБ в начале до 2075 в конце (см. Первую и последнюю строку на скриншоте) даже после вызова g c .collect (). Код показан ниже. Снимок экрана дополнительно показывает вывод tracemalloc
.
Поскольку это выполняется внутри функции, я ожидал, что все локальные переменные будут очищены при возврате. Интересно, что когда я del
данные внутри функции, проблема исчезает для случая, когда я генерирую данные образца внутри функции.
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 ГБ дополнительного использования памяти).
Любые идеи о том, что происходит или как дальше отследить проблему ?