programing

Angular 어플리케이션에서 메모리 누수를 포착하는 방법

madecode 2023. 2. 22. 23:22
반응형

Angular 어플리케이션에서 메모리 누수를 포착하는 방법

나는 Angular로 쓰여진 웹 앱을 가지고 있다.기본적으로 API를 2개의 엔드포인트에 폴링하는 JS.그래서 매분마다 새로운 것이 있는지 여부를 조사한다.

메모리 누수가 적다는 것을 알게 되어 최선을 다해 찾았지만 할 수 없습니다.그 과정에서 앱의 메모리 사용량을 줄일 수 있었습니다.그것은 훌륭합니다.

다른 작업을 하지 않아도 모든 여론조사에서 메모리 사용량이 급증(정상)한 후 감소하지만 항상 증가합니다.레레의 i i에서 .[]로로 합니다.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 - 약속 추가 쇼케이스:

은 것은입니다.makeRequest이는 다음 2개의 서비스에서 사용되는 기능입니다.

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 - 이미지 내 열기(배열) 트리

여기에 이미지 설명 입력

다 그런 거라서 쓸모가 없어 :)

또, 다음의 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개의 새로운 더미가 있다.

정답은 캐시입니다.

히프 스냅샷 분석

뭔지는 모르겠지만, 이건 점점 커져요.jQuery와 관련된 것 같습니다.jQuery 요소 캐시일 수도 있습니다.혹시 서비스 호출 후 1개 이상의 요소에 jQuery 플러그인을 적용합니까?

갱신하다

문제는 HTML 요소가 추가되어 jQuery로 처리되지만(예를 들어 popbox 플러그인을 통해), 전혀 삭제되지 않거나 jQuery로 삭제되지 않는다는 것입니다.이 경우 처리란 이벤트 핸들러를 추가하는 것을 의미합니다.캐시 오브젝트(용도가 무엇이든) 내의 엔트리는 jQuery가 요소가 삭제되었음을 알고 있는 경우에만 삭제됩니다.jQuery를 사용하여 요소를 제거해야 합니다.

업데이트 2

jQuery를 때문에 내의 되지 않은 angular jQuery는 jQuery를 합니다., 되어 있는 인에 되어 있습니다.를 해제하고 AFAIK Antonio 내의 데이터를 하도록 플러그인 했습니다.destroy()누수는 되었습니다.이것으로 메모리 누수는 해소되었습니다.

메모리 누수를 수정하는 표준 브라우저 방법은 페이지를 새로 고치는 것입니다.JavaScript의 가비지 컬렉션은 느리고 이 점에 의존한 것 같습니다.또한 Angular는 보통 SPA이기 때문에 브라우저는 갱신할 수 없습니다.

하지만 한 가지 장점이 있습니다. Javascript는 주로 하향식 계층 언어입니다. 아래에서 위로 메모리 누수를 검색하는 대신 위에서 아래로 메모리 누수를 제거할 수 있습니다.

그래서 저는 이 솔루션을 생각해 냈습니다.이 솔루션은 작동하지만 앱에 따라 100% 효과가 있을 수도 있고 없을 수도 있습니다.

홈페이지

와 Angular로 .ng-view ★★★★★★★★★★★★★★★★★★.

<div ng-controller="MainController as vm"> <div id="main-content-app" ng-view></div> </div>

컨트롤러

그런 다음 컨트롤러에서 앱을 "새로고침"하기 위해, 우리는 jQuery의 .empty()와 Angular의 .empty()를 중복 호출하여 크로스 라이브러리 참조가 지워졌는지 확인합니다.

function refreshApp() {
var host = document.getElementById('main-content-app');
if(host) {
    var mainDiv = $("#main-content-app");
    mainDiv.empty();
    angular.element(host).empty();
}
}

라우팅이 시작되기 전에 위의 콜을 호출하여 페이지 새로고침을 시뮬레이트합니다.

$rootScope.$on('$routeChangeStart',
function (event, next, current) {
    refreshApp();
}
);

결과

이것은 「브라우저 타입의 동작의 갱신」을 실시해, DOM 를 클리어 해, 리크도 클리어 하는, 일종의 해킹 방식입니다.도움이 됐으면 좋겠다.

언급URL : https://stackoverflow.com/questions/20654684/how-to-catch-memory-leaks-in-an-angular-application

반응형