Jan. 31st, 2017

Предположим, где-то в начале своего приложения для node я напишу что-то вроде:

String.prototype.copy = function() {
    return (this+' ').trim();
};

Что из этого выйдет? Простая вещь – поведение объекта String изменится во всех модулях подключаемых через require, включая написанные не мной. Прикол в том, что тоже самое можно сделать в любом модуле, в любое время.

В данном случае ничего ужасного скорей всего не произойдет, но потенциально такая возможность открывает просто непаханное поле для разнообразных, трудноуловимых глюков. Можно испортить какой-то глобальный объект, причем как случайно, так и намеренно, но в зависимоти от фазы луны. Найти причину конечно всегда воможно. Тупо просматривая исходники всех модулей, ага. Потому что ошибка будет проявляться случайным образом в самых разных местах.

P.S. Хочу немножко поэкспериментировать со сборщиком мусора. А то у меня волосы начинают вставать дыбом, когда я задумываюсь о потенциальных утечках памяти.

Попробовал воспроизвести ситуацию в которой у меня были утечки памяти. Воспроизвел в лучшем виде. Осталось разобраться что происходит.

Делаю снапшоты и сравниваю в браузере. А вот хуй. Браузер замечательно показывает что размер одного снапшота 654 метра, второго 10. Смотрим детали – видим фигу. В деталях нихера нет. Т.е. понятно что память теряется, но штатными средствами понять что происходит не получается.

Причем, если я генерирую файл сам, то ничего особенно ужасного не происходит. память если и течет, то совсем чуточку. А вот страничка взятая с LJ вызывает у ноды корчи и ее прет как на дрожжах. Но ровно до тех пор пока я не делаю “безопасное” сохранение полученных строк. Проблема в том, что если бы дело было именно в этом, то это должно точно также работать на моем собственном файле. Должна быть та же проблема и то же лекарство. Этого не происходит и значит дело в чем-то другом.

Я исключил вариант что для парсинга ЖЖ-страницы выделяется как-то особенно много памяти. Фактически происходит наоборот – для моей странички выделяется больше памяти, но и освобождается она большими кусками. Для ЖЖшной памяти надо меньше, но освобождается она неадекватно маленькими порциями и в результате объем растет.

И как я ни кручу эту строку – это самая обычная строка. Точно такая же как после преобразования +- пробел. И она не должна быть к чему-то привязана и удерживать это что-то от удаления.

Воспроизвел эффект на своём файле. Вытаскиваемые строки должны быть разные. Похоже что если они одинаковые – нода их как-то по-тихому оптимизирует, маскируя проблему с утечками.

Это хорошо.

В смысле – все конечно плохо, но когда проблема воспроизводится ее можно решить с помощью костылей, поскольку понятно когда их надо подставлять.

Догадался посмотреть что делает cheerio.text(), каким таким извращенным способом она формирует строку, что потом ее надо выковыривать из контекста отбойным молотком… Охуел от увиденного – самая обычная функция, формирует строку самым тривиальнейшим образом. Ровным счетом ничего подозрительного.

P.S. Может ли объект выглядеть как примитивная строка при любых способах получить его значение, но при этом строкой не являться? Я так и не нашел способа провернуть такой трюк. Так что я исключаю возможность что мне передается не примитивная строка, а что-то под видом строки. Ссылки на примитивные типы в JavaScript не поддерживаются. Значит это дефект самого движка V8, который проявляется в каких-то определенных обстоятельствах. Но я до конца не понимаю в каких.

Page generated Jun. 10th, 2025 10:35 pm
Powered by Dreamwidth Studios