#javascript #node.js #file-io #memory-leaks
#javascript #node.js #file-io #утечки памяти
Вопрос:
Я использую node.js считывать изображение каждую секунду. Идея состоит в том, чтобы позже перенести его в веб-браузеры, превратив в простой поток. Код выглядит следующим образом:
var fs = require("fs");
var intervalTimerObj;
function startStream() {
if(!intervalTimerObj) {
intervalTimerObj = setInterval( updateStream , 1000);
}
}
function updateStream(){
fs.readFile( __dirname "/pic.jpg", function(err, image) {
});
}
startStream();
При выполнении приведенного выше кода я, похоже, получаю утечку памяти, поскольку моя память быстро заполняется.
Чем больше загружаемый файл изображения, тем быстрее он заполняется.
Что я делаю не так? Есть ли какой-нибудь способ «освободить» переменную изображения? Я пытался свести его к нулю.
Комментарии:
1. Не используйте
setInterval
функцию обновить поток, когда вы закончили чтение изображения приfs.readFile
обратном вызове. лучше прочитать изображение, а затем, если вам действительно нужен этот интервал в 1000 мс, использоватьsetTimeout
его для начала следующего чтения2. Просто попытался вместо этого использовать setTimeout. Все еще продолжает красть всю мою память.
3. В любом случае, почему ты делаешь это каждые 1000 мс?
4. Идея состоит в том, чтобы каждую секунду делать снимок, а затем передавать его в веб-браузеры с помощью socket.io
Ответ №1:
Это лучший подход. setInterval()
здесь не следует использовать, поскольку это может привести к одновременному выполнению одной и той же задачи. Используйте setTimeout()
вместо этого. Идеальное место для этого readFile()
— обратный вызов inside:
var fs = require("fs");
var timeoutHandle = null;
function startTimeout() {
stopTimeout();
timeoutHandle = setTimeout(updateStream, 1000);
}
function stopTimeout() {
clearTimeout(timeoutHandle);
}
function updateStream(){
fs.readFile( __dirname "/pic.jpg", function(err, image) {
// ...
startTimeout(); // Make sure this line is always executed
});
}
startTimeout();
Вам также необходимо убедиться, что вы не сохраняете никаких ссылок на image
после его обработки, иначе сборщик мусора V8 не освободит данные изображения, что приведет к утечке памяти.
Комментарии:
1. Я запускаю вашу функцию startTimeout, но все равно память никогда не освобождается. Каждый раз, когда загружается изображение, моя память увеличивается. Работает ли startTimeout для вас?
2. Я долго тестировал ваше решение, и, похоже, использование памяти стабилизируется при использовании памяти ~ 40% (200 МБ). Этого следовало ожидать? Кстати, спасибо за код!
3. Да, это кажется нормальным. Вы должны быть очень осторожны при работе с большими объемами данных внутри циклов. Рад помочь!
Ответ №2:
Попробуйте это
function startStream() {
if(!intervalTimerObj) {
intervalTimerObj = setTimeout( updateStream , 1000);
}
}
function updateStream(){
fs.readFile( __dirname "/pic.jpg", function(err, image) {
//OK file is read
//do yoyr stuff with it....
// Now start next read
startStream()
});
}
startStream();
Комментарии:
1. Спасибо за код. Тем не менее, моя память постоянно увеличивается. Я отслеживаю оперативную память с помощью команды top (используя Linux), и она никогда не отключается.
2. Я предполагаю, что вы где-то входите в цикл вызовов circle. Проверьте свой код, отладьте, если возможно, и придумайте лучший шаблон. Если новая проблема вернется, отправьте вопрос. Этот код является таким шаблоном. 2 функции вызывают друг друга