Рубрики
Без рубрики

Устранение неисправностей Утечки памяти Nodejs с узлом Memwatch

Я недавно выпустил свой социальный рисунок Draw.wtf, где вы соревнуетесь друг с другом, рисуя … Теги с учебником, узлом, JavaScript.

Я недавно выпустил свой социальный рисунок Draw.wtf Где вы соревнуетесь друг с другом, рисуя вещи и оцениваемся по модели машины обучения. Пока я получил много положительных отзывов, так как я выпустил его, я также быстро обнаружил, что что-то был неправ. Бэкэнда для игры написана в Гнездо (Узел) и размещены на Heroku (который я могу действительно рекомендовать, их свободный уровень отлично подходит для страстных проектов). Но, глядя на использование памяти в обзор метрики, я мог бы ясно видеть, что вещи, которые мы не в порядке:

Там не было никаких способов использовать эту большую память, поэтому было ясно, что у меня была утечка памяти .

Утечка памяти заключается в том, когда приложение использует память (RAM), не отпустив его. Наиболее современный (высокий уровень) языки программирования сегодня реализуют какую-то автоматическую очистку неиспользуемой памяти и узла использует что-то называемое A «Мусорный коллектор» Отказ Ради этой истории отладки, это все, что вам нужно знать!

Вернуться к проблеме в draw.wtf! Я почти только работал на языках с сборкой мусора, поэтому, начнем устранить эту проблему, у меня не имел опыта с нахождением утечек памяти. Моя первая мысль была просто прокрутить код и найти проблему Бууота безрезультатно. Я понятия не имел, где в коде ошибок может жить, и так как мы не делаем никакой ручной обработки памяти там не должен существуют какие-либо ошибки!:(

Следующим шагом было достичь наиболее распространенного инструмента в каждом разработчике Toolbox: Google!

Я читаю много Из статей о нахождении проблем памяти в узле, но никто не привел меня близко к решению. Наконец я нашел статью, которая рекомендовала библиотеку Узел-memwatch который выглядел многообещающим! К сожалению, это не обновлено в течение 7 лет …

Открытый источник для спасения! 🚀

Глядя на Формы узла-Memwatch мы можем попробовать найти тот, который все еще поддерживается, и после просмотра пары я оказался Эта вилка от Airbnb.

Вернитесь в код, который я начал с тестирования библиотеков Куча отличается Бег Новый Memwatch. Heapdiff (); и Heapdiff.end (); который выводит до и после использования памяти. И конечно, достаточно, я вижу, что память растут примерно на 2 МБ для каждого раунда в игре.

Одна вещь, которую я обнаружил, когда тестирование это было то, что память не Расти, когда я ничего не нарисовал! 🤔 Это было действительно здорово, так как он сузился, где в коде в этом вопросе. С этими знаниями я переместил дифференцированные функции кучи на пару разных мест, где обрабатываются нарисованные линии, и это привело меня к функции, которая была протекающей памятью: вычисление баллов.

Для расчета баллов у меня есть модель обучения машины, обученной Azure Custom Vision а затем пробегает его локально с Tensorflow Отказ Вот реализация этой функции расчета, с проблемой утечки памяти не повреждена:

async function calculate(pixels) {
  const inputs =
    pixels instanceof tf.Tensor
      ? pixels
      : this._preprocess(tf.browser.fromPixels(pixels, 3))

  const outputs = await this.model.execute(inputs, null)

  const arrays = !Array.isArray(outputs)
    ? await outputs.array()
    : Promise.all(outputs.map(t => t.array()))

  const result = Array.isArray(arrays[0])
    ? arrays[0].map((x, i) => ({ probability: x, tag: this.tags[i] }))
    : []

  return result
}

Вы видите проблему? (Это не в _preprocess Функция).

Я уверен, что несмотря ни на что я смотрел на этот код, так что дальше я погрузился в документацию Tensorflow.js, где я нашел Этот маленький самородок мудрости:

«При использовании Backend WebGL TF. Память тензорной памяти должна быть безупречна (не достаточно, чтобы позволить TF. Tensor выйдет из прицела для его памяти, которая будет выпущена). “

Аааа, решение! С этим было не очень трудно прочитать дополнительную документацию и в конечном итоге с расчетом счет, который работает:

async function calculate(pixels) {
  const inputs = tf.tidy(() => {
    return pixels instanceof tf.Tensor
      ? pixels
      : this._preprocess(tf.browser.fromPixels(pixels, 3))
  })

  const outputs = await this.model.execute(inputs, null)

  const arrays = !Array.isArray(outputs)
    ? await outputs.array()
    : Promise.all(outputs.map(t => t.array()))

  const result = Array.isArray(arrays[0])
    ? arrays[0].map((x, i) => ({ probability: x, tag: this.tags[i] }))
    : []

  inputs.dispose()
  Array.isArray(outputs) ? outputs.forEach(o => o.dispose()) : outputs.dispose()

  return result
}

tf.tidy () автоматически располагает любой тф Тензор Создано внутри, а потом я бегу вручную утилизировать () На любом тензоре я должен создать за пределами этого. И это все! Теперь память больше не протекает:

Чтобы закончить это, если вы собираетесь взять что-нибудь с вами из этого поста, я думаю, что это должно быть так Узел-memwatch это довольно хороший инструмент для устранения неисправностей проблем с памятью. Если есть что-то, что вы должны не Возьмите с собой, это, вероятно, образцы кода. Я понятия не имею, если они хорошие, плохие или уродливые 😅

Вы бы решили это другим способом? Дай мне знать в комментариях!

Оригинал: “https://dev.to/awnton/troubleshooting-nodejs-memory-leaks-with-node-memwatch-5fpp”