问题描述
我有一个Web应用程序写在AngularJS基本上投票站两个端点的API。所以,每分钟轮询,看看是否有什么新的。
I have a webapp written in AngularJS which basically polls an API to two endpoints. So, every minute it polls to see if there is anything new.
我发现它有一个小的内存泄漏,我已经做了我所能找到它,但我不能做到这一点。在这个过程中我已经成功地减少我的应用程序,这是伟大的内存使用情况。
I discovered that it has a small memory leak and I've done my best to find it but I'm not able to do it. In the process I've managed to reduce the memory usage of my app, which is great.
如果没有做其他事情,每一个调查,你可以看到在内存使用量激增(这是正常的),然后就应该下降,但它总是不断增加。我已经改变了阵列的清洁从 []
到 array.length = 0
,我想我确保引用不持续存在,因此它不应该被保留的这一点。
Without doing anything else, every poll you can see a spike in the memory usage (that's normal) and then it should drop, but it's always increasing. I've changed the cleaning of the arrays from []
to array.length = 0
and I think I'm sure that references don't persist so it shouldn't be retaining any of this.
我也试过这样:https://github.com/angular/angular.js/issues/1522
但没有任何运气...
But without any luck...
所以,这是两个堆之间的比较:
So, this is a comparison between two heaps:
大部分泄漏似乎来自(阵列),如果我打开,是该阵列由API调用的返回解析,但我敢肯定,他们不会被存储:
Most of the leak seems to come from (array) which, if I open, are the arrays returned by the parsing of the API call but I'm sure they're not being stored:
这是基本结构:
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
服务,因此,这将是服务
变量的值。
Basically, let's say I have a sellings
service so, that would be the value of the service
variable.
然后,在主视图:
$scope.$on('api.sellings', function(event, data) {
$scope.sellings.length = 0;
$scope.sellings = data;
});
和观点确实有一个 ngRepeat
需要这使得这一点。我花了很多时间试图通过自己算出这个我不能。我知道这是一个很难的问题,但是,也有人对如何追踪下来?任何想法
And the view does have an ngRepeat
which renders this as needed. I spent a lot of time trying to figure this out by myself and I couldn't. I know this is a hard issue but, do anyone have any idea on how to track this down?
编辑1 - 添加无极展示:
Edit 1 - Adding Promise showcase:
这是 makeRequest的
这是由两个服务所使用的功能:
This is makeRequest
which is the function used by the two services:
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');
}
});
如果我注释掉 $范围。在$('api.sellings')
部分泄漏仍然存在,但下降到1%。
If I comment out the $scope.$on('api.sellings')
part, the leakage still exists but drops to 1%.
PS:我使用的是最新版本的角迄今
PS: I'm using latest Angular version to date
编辑2 - 图像中开幕(阵列)树
Edit 2 - Opening (array) tree in an image
这一切就像所以它是相当无用恕我直言:(
It's everything like that so it's quite useless imho :(
此外,这里有4堆报告,以便你可以发挥自己:
Also, here are 4 heap reports so you can play yourself:
https://www.dropbox.com/s/ys3fxyewgdanw5c/Heap.zip
编辑3 - 为应对@zeroflagL
Edit 3 - In response to @zeroflagL
编辑指令,没有对泄漏产生任何影响,虽然封盖似乎更好,因为它没有显示jQuery的高速缓存的东西呢?
Editing the directive, didn't have any impact on the leak although the closure part seems to be better since it's not showing jQuery cache things?
该指令现在看起来像这样
The directive now looks like this
var destroy = function(){
if (cls){
stopObserving();
cls.destroy();
cls = null;
}
};
el.on('$destroy', destroy);
scope.$on('$destroy', destroy);
要我来说,这似乎是发生了什么是(阵列)上
部分。还有的英寸
To me, it seems that what's happening is on the (array)
part. There is also 3 new heaps in between pollings.
推荐答案
和答案是缓存。
我不知道它是什么,但是这件事情的增长。这似乎是与jQuery的。也许这是jQuery的元素缓存。万一你每一个服务调用后一个或多个元素应用一个jQuery插件?
I don't know what it is, but this thing grows. It seems to be related to jQuery. Maybe it's the jQuery element cache. Do you by any chance apply a jQuery plugin on one or more elements after every service call?
的问题是,HTML添加元素,使用jQuery处理(例如经由popbox插件),但无论是从来没有在所有已移除或不与jQuery除去。在这种情况下,处理手段的东西,如添加事件处理。在缓存中的对象(无论它是)的条目,如果知道的jQuery的内容已经取消只做移除。即元件必须与jQuery除去。
The problem is that HTML elements are added, processed with jQuery (e.g. via the popbox plugin), but either never removed at all or not removed with jQuery. To process in this case means stuff like adding event handlers. The entries in the cache object (whatever it is for) do only get removed if jQuery knows that the elements have been removed. That is the elements have to be removed with jQuery.
这不是很清楚为什么在缓存中的这些条目没有被删除,因为角度应该使用jQuery,当它包括在内。但他们已通过评价和包含事件处理程序和数据中提到的插件添加。据我所知安东尼改变了插件code取消绑定事件处理程序和插件的删除数据的destroy()
方法。最终删除了内存泄漏。
It's not quite clear why these entries in the cache haven't been removed, as angular is supposed to use jQuery, when it's included. But they have been added through the plugin mentioned in the comments and contained event handlers and data. AFAIK Antonio has changed the plugin code to unbind the event handlers and remove the data in the plugin's destroy()
method. That eventually removed the memory leak.
这篇关于如何捕捉内存泄漏在角应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!