У меня есть webapp, написанный в AngularJS, который в основном опроса API для двух конечных точек. Итак, каждую минуту он опросает, есть ли что-то новое.
Я обнаружил, что у него небольшая утечка памяти, и я сделал все возможное, чтобы найти его, но я не могу этого сделать. В этом процессе мне удалось уменьшить использование памяти в моем приложении, и это здорово.
Не делая ничего другого, каждый опрос вы можете увидеть всплеск в использовании памяти (что нормальный), а затем он должен упасть, но он всегда увеличивается. Я изменил очистку массивов от []
до array.length = 0
, и я думаю, что я уверен, что ссылки не сохраняются, поэтому не следует сохранять это.
Я также пробовал это: https://github.com/angular/angular.js/issues/1522
Но без везения...
Итак, это сравнение между двумя кучами:
Большая часть утечки, по-видимому, поступает из (массива), которые, если я открываю, являются массивами, возвращаемыми анализом вызова API, но я уверен, что они не хранятся:
Это в основном структура:
poll: function(service) {
var self = this;
log('Polling for %s', service);
this[service].get().then(function(response) {
if (!response) {
return;
}
var interval = response.headers ? (parseInt(response.headers('X-Poll-Interval'), 10) || 60) : 60;
services[service].timeout = setTimeout(function(){
$rootScope.$apply(function(){
self.poll(service);
});
}, interval * 1000);
services[service].lastRead = new Date();
$rootScope.$broadcast('api.'+service, response.data);
});
}
В принципе, скажем, у меня есть служба sellings
, поэтому это будет значение переменной service
.
Затем в главном представлении:
$scope.$on('api.sellings', function(event, data) {
$scope.sellings.length = 0;
$scope.sellings = data;
});
И представление имеет ngRepeat
, который отображает это по мере необходимости. Я потратил много времени, пытаясь понять это сам, и я не мог. Я знаю, что это сложная проблема, но есть ли у кого-нибудь идеи о том, как отслеживать это?
Редактировать 1 - Добавление демонстрации Promise:
Это makeRequest
, который является функцией, используемой двумя службами:
return $http(options).then(function(response) {
if (response.data.message) {
log('api.error', response.data);
}
if (response.data.message == 'Server Error') {
return $q.reject();
}
if (response.data.message == 'Bad credentials' || response.data.message == 'Maximum number of login attempts exceeded') {
$rootScope.$broadcast('api.unauthorized');
return $q.reject();
}
return response;
}, function(response) {
if (response.status == 401 || response.status == 403) {
$rootScope.$broadcast('api.unauthorized');
}
});
Если я прокомментирую часть $scope.$on('api.sellings')
, утечка все еще существует, но падает до 1%.
PS: Я использую последнюю версию Angular на сегодняшний день
Изменить 2 - Открыть (массив) дерево в изображении
Это все так, что это совершенно бесполезно imho: (
Кроме того, здесь есть 4 отчета о кучах, чтобы вы могли играть сами:
https://www.dropbox.com/s/ys3fxyewgdanw5c/Heap.zip
Изменить 3 - В ответ на @zeroflagL
Редактирование директивы не оказало никакого влияния на утечку, хотя закрывающая часть кажется лучше, поскольку она не показывает вещи кеша jQuery?
Теперь директива выглядит так:
var destroy = function(){
if (cls){
stopObserving();
cls.destroy();
cls = null;
}
};
el.on('$destroy', destroy);
scope.$on('$destroy', destroy);
Для меня, похоже, что происходит в части (array)
. Существует также 3 новых кучи между опросами.