Я исследую утечку памяти (или «раздувание») в приложении Python (3.5.2) с использованием OpenCV (3.4.1, локальная сборка) в Ubuntu 16.04 (x86).
Приложение очень часто записывает изображения в файл и для этой цели использует метод .imwrite()
. Я обнаружил, что при использовании .imwrite()
использование оперативной памяти становится диким, но я не могу найти причину такого поведения.
Для устранения этой проблемы я подготовил простой тестовый скрипт:
#!/usr/bin/python3
import cv2
import time
img = cv2.imread("vista.jpg")
idx = 0
while True:
filename = "/tmp/vista_copy_" + str(idx) + ".tiff"
cv2.imwrite(filename, img)
idx = idx + 1
time.sleep(1)
Во время выполнения этого скрипта я следил за свободной оперативной памятью (пробует свободную память каждые 10 секунд):
$ while [ 1 ] ; do grep MemFree /proc/meminfo ; sleep 10 ; done
MemFree: 898024 kB
MemFree: 780640 kB
MemFree: 667848 kB
MemFree: 545700 kB
MemFree: 437196 kB
MemFree: 315820 kB
MemFree: 298380 kB
MemFree: 298292 kB
MemFree: 297448 kB
MemFree: 297080 kB
MemFree: 915616 kB
Последний пример, когда свободная память возвращается к своему начальному значению, был взят после того, как я удалил файлы изображений из цели, что может указывать на то, что это проблема ОС, или, возможно, файлы не закрываются должным образом программа (хотя я не мог найти подсказку для этого в исходном коде C ++).
Я нахожу это поведение очень странным, даже более того, потому что imwrite - такой основной метод. Кто-нибудь может помочь в отладке и решении этой проблемы?
Редактировать
Таким образом, очевидно, что потребление памяти в моем тестовом скрипте связано с тем, что / tmp на самом деле является RAM-диском, но проблема сохраняется при записи на внешний диск, подключенный через адаптер Ethernet.
Обновление
Проблема воспроизводится при записи в локальную папку на физическом диске. Похоже, что это общая проблема ОС, не относящаяся конкретно к imwrite. Операционная система кэширует файлы, но никогда не освобождает этот кэш (возможно, она «думает», что у нее достаточно памяти для всего этого кэширования).
Выполнение 'echo 3 > /proc/sys/vm/drop_caches'
периодически, как предложено здесь и здесь - разумный обходной путь, но мы бы хотели менее навязчивое / насильственное решение, которое помешает системе использовать много кеша, или это сделает его свободным без кеша.