Как стать автором
Обновить

Комментарии 15

Поняв, что проблемы были вызваны именно глубокими объектами, мы легко нашли их источник. Их создавала библиотека dnscashe, добавленная в проекты много лет назад. Из-за различных изменений в нашей инфраструктуре она стала вести себя иначе — встроенный в неё кеш начал переполняться и перестал корректно очищаться.

Убийца садовник!
очень, очень приятно было прочитать что-то на техническом, про поиск WTF

Hidden text

Отличная статья, только я так и не понял, при чем тут было глубокое дерево, если проблема в итоге была в не очистке кэша?) Вообще, я когда статью начинал читать, сразу подумал, "а нет ли у них там кэша, который не очищается нормально?") Оказалось так и было) А почему я так подумал, потому что кроме утечек-утечек, кэш - еще один патологический пожиратель памяти. Но работу вы провели великолепную, читал с удовольствием.

Иначе статьи бы не получилось. "У нас текла память внутри двести лет как заброшенной библиотеки, которую мы ленились выкинусь из кодовой базы".

Фишка в том, что сам кеш прирастал не больше чем на 1 мб в день. В самом жирном дампе, который мы потрошили он был около 3 мб.

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

Большая часть памяти была занята именно ни чем не удерживаемыми объектами, без каких либо retainers. Ответы от других сервисов, куски html который отдавал сам сервис и тд. При полном снятии нагрузки с сервиса - память на нем приходила в норму спустя некоторое время.

Паждите-ка, что-то не сходится. Если утечка была небольшой, почему вы падали по OOM?

Если очень коротко, то память росла из-за объектов, которые gc должен был удалить, но он не мог сделать из-за большого дерева, которое генерируется ошибкой в сторонней библиотеке.

Размер объектов дерева оказался не существенным, а вот его вложенность - значительно замедляла работу gc.

Про то же и статья - утечка как бы есть, но ее как бы и нет. GC вполне мог удалить все объекты, но просто напросто не успевал.

Вообще по памяти легко можно падать просто из-за CPU ограничений. Простой эксперимент который можно произвести - запустить одинаковый тест который просто должен на каждый запрос выделять память а затем освобождать ее. И запустить его на мощном CPU и на маленькой слабенькой виртуалке, выделив и там и там одинаковое кол-во old space.

Быстрый процессор будет намного эффективнее гонять GC и не упадет намного дольше чем слабенький, не смотря на то что памяти и там и там вроде как одинаковый объем.

просто напросто не успевал.

Что значит "не успевал"? Если рантайм пришёл в состояние "в хипе негде аллоцировать объект", он должен всё запаузить, собрать мусор и продолжить работать дальше, не вызывая никаких OOM. Node работает не так?

Да, тоже ожидал бы подобного поведения.

Но нет, GC в v8 давно уже стал делать mark-фазу в соседнем потоке, при этом кажется что какой то отдельной логики по тому, чтобы сделать ее в основном потоке если все очень плохо - нету. Тут я все же говорю "кажется", потому что особо информации по этому поводу не видел и чтобы ответить с уверенностью - нужно видимо лезть в исходники самого v8 и смотреть что там и как

Вот это меня и зацепило. У вас нет убедительного ответа на вопрос "при чем тут вообще миллионы промисов".

А то может на самом деле ваша проблема в том что максимальный размер хипа ноды настроен таким образом, что не помещается в лимиты по памяти докер-контейнера.

Люто плюсую! Что в яве, что в питоне перед тем как упасть с ООМ будет обязательный stop-the-world с полной очисткой всего. А так выглядит как ошибка реализации самого GC, не успел почистить память, значит можно упасть с ООМ. И как это дебажить вообще?

Вообще ни разу ничего не писал на ноде и даже js не знаю, но так интересно было почитать!

Крутая статья и графики красивые!

О проблеме в багтрекер V8 написали?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий