Память Nodejs заполняется слишком быстро при загрузке изображений ~ 10 МБ - PullRequest
1 голос
/ 29 мая 2019

Резюме

Загрузка изображения из серверной части Nodejs в AWS S3 через JIMP заполняет кучу памяти.

Workflow

  1. Frontend (реагирует) отправляет изображение через форму отправки в API
  2. Сервер анализирует данные формы
  3. JIMP поворачивает изображение
  4. JIMP изменяет размер изображения, если ширина> 1980px
  5. JIMP создает буфер
  6. Буфер загружается на S3
  7. Обещание разрешено -> Метаданные изображения (URL, имя корзины, индекс и т. Д.), Сохраненные в базе данных (MongoDB)

Фон

Сервер размещен на Heroku с оперативной памятью всего 512 МБ. Загрузка небольших изображений и все другие запросы работают нормально. Тем не менее, приложение вылетает при загрузке одного изображения размером более ~ 8 МБ, когда в сети только один пользователь.

Расследование до настоящего времени

Я пытался повторить это в моей локальной среде. Поскольку у меня нет ограничения памяти, приложение не будет аварийно завершать работу, но при загрузке изображения размером 10 МБ используется около 870 МБ. Образ 6 МБ остается около 60 МБ оперативной памяти. Я обновил все пакеты npm и попытался отключить любую обработку изображения.

Я пытался искать утечки памяти, как показано на следующих снимках экрана, однако, следуя тому же рабочему процессу, что и выше, для того же изображения (6 МБ) и делая 3 снимка кучи, мы получаем около 60 МБ памяти.

Во-первых, я подумал, что проблема в том, что обработка изображения (изменение размера) занимает слишком много памяти, но это не объясняет большой разрыв между 60 МБ (для изображения 6 МБ) и около 800 МБ для изображения 10 МБ.

Тогда я подумал, что это связано с элементом "system / JSArrayBufferData" (см. Ссылку 2), который занимает около 30% памяти. Тем не менее, этот пункт всегда есть, даже я не загружаю изображение. Он появляется только перед тем, как я остановлю снимок записи на вкладке «Память» в разделе «Инструменты разработчика Chrome». Тем не менее, я все еще не уверен на 100%, что именно.

Теперь я считаю, что это связано с «TimeList» (видно в ref3). Я думаю, что это связано с тайм-аутами в ожидании загрузки файла на S3. Однако и здесь я абсолютно не уверен, почему это происходит.

Ниже приведены снимки экрана, на мой взгляд, важных частей снимков Chrome Inspector, работающих на сервере на nodejs с флагом --inspect.

Ref1: Показывает полные элементы 3-го снимка - все 3 снимка загрузили одно и то же изображение размером 6 МБ. Мусор кажется правильно собранным, так как объем памяти не увеличился Ref2: Показывает окончание третьего снимка, непосредственно перед тем, как я остановил запись. Не уверены, что такое «system / JSArrayBufferData». Ref3: Показывает конец 5-го снимка, это изображение с размером 10 МБ. Эти маленькие непрерывные всплески - это элементы «TimeList», которые, похоже, связаны с тайм-аутом. Кажется, они появляются, когда сервер ожидает ответа от AWS. Также кажется, что это то, что заполняет память, так как этот элемент отсутствует при загрузке чего-то менее 10 МБ.

Ref4: Показывает немедленное завершение 5-го снимка непосредственно перед остановкой записи. «system / JSArrayBufferData» появляется снова, но только в конце.

Вопрос

К сожалению, я не уверен, как сформулировать свой вопрос, поскольку я не знаю, в чем проблема или на что мне действительно нужно обратить внимание. Буду очень признателен за любые советы или опыт.

1 Ответ

1 голос
/ 02 июня 2019

высокое потребление памяти было вызвано пакетом «Jimp», который использовался для чтения файла, его поворота, изменения размера и создания буфера для загрузки в систему хранения файлов.

Часть чтения файла, то есть Jimp.read ('filename'), вызвала проблему с памятью. Это известная ошибка, как видно здесь: https://github.com/oliver-moran/jimp/issues/153

К настоящему моменту я переключился на пакет обработки «острых» изображений и теперь могу легко загружать изображения и видео размером более 10 МБ.

Надеюсь, это поможет и людям, сталкивающимся с этим.

Приветствия

...