32

google 크롬 (버전 20.0.1132.47, Ubuntu 11.04 64 비트)에서 가비지 콜렉션에 관한 질문이 있습니다.'bound_this'로만 참조되는 인스턴스는 가비지 수집되지 않습니다.

힙 덤프를 비교하고 메모리 누수를 검사하는 동안 절대로 제거되지 않은 인스턴스가 발견되었습니다. 일반적으로이 동작은 프로그래머가 오류로 추적하지만,이 경우에는 차라리 우둔 해요 할 수 있습니다 ..

Screenshot of heap-dump showing an instance (child) referenced only by 'bound_this'

이 인스턴스는 '610739 @ 아이가'참조 다음 스크린 샷에서보세요 자식 인스턴스 자체의 함수에 속하는 'bound_this'인스턴스에 의해서만 가능합니다. 내 이해를 위해 자식 인스턴스는 가비지 수집되어야합니다. 다른 참조는 자식 인스턴스 자체 ('bound_this'함수를 통해)를 유지합니다.

내가 ( ECMA Script wiki on bound_this)

나는 여기에 분명하고 그렇다면 뭔가 실종 크롬의 'native_bind'기능에 매핑 underscore.js ''bindAll '유틸리티 기능 (underscore.js#bindAll)를 사용하고

가, 누군가가 설명 할 수 이 인스턴스들을 살아있게 유지하는 것은 무엇입니까?

업데이트 : chrominium에서 동일한 응용 프로그램을 테스트 한편 (18.0.1025.168 (개발자 빌드 134367 리눅스) 우분투 11.10)이 매달려 인스턴스를 표시하지 않습니다 ..

업데이트 2에서
:
는 다음 Esailijas는 jsfiddle 스 니펫을 제공하기 위해 힌트를 얻었습니다. 기본적으로 내가하는 것을 모방 한 하나 (http://jsfiddle.net/8gSTR/1/)를 만들었습니다. 이 바이올린을 실행하면 불행히도 응용 프로그램에서 겪고있는 잘못된 행동이 표시되지 않습니다. 내 경우에는없는 Heap-dump taken during execution of jsfiddle mentioned above

같은 기준으로 : A'-인스턴스가 여전히 참조하는 '동안 수행 힙 덤프 살아 인스턴스를 유지하는 window.o 배열의 기준에도 불구하고 있지만 비슷한 종류의 보이는 (스크린 샷 1) 크롬이이 인스턴스를 해제하지 못하게하는 이유는 무엇인지 모르겠다. ...

업데이트 3 :
숨겨진 속성을 사용하려면 loislos advice가 뒤 따른다. 그 결과 (지점 중 하나가 확장 됨) 다음 스크린 샷에서 볼 수 있지만 더 이상 나를 데려 가지 않습니다. Heap-dump with hidden properties enabled

+0

여기를 보지 못함 http://jsfiddle.net/uGX22/3/. 처음에는 그들은 거기에 있습니다 (힙 17 복용.3200bp에서 60000 개의 클로저로), 몇 분 기다렸다가 새로운 스냅 샷을 찍었고 힙은 6MB로 돌아 왔고 클로저는 사라졌습니다. 이걸 재현 할 수 있을까요? – Esailija

+0

이 상황을 만든 코드를 보여 주시겠습니까? 나는 디버거의 스크린 샷에서 그것을 얻지 못한다. – Bergi

+0

문제를 재현하기 위해 약간의 스 니펫을 만들려고 노력할 것입니다. 상황을 만든 코드는 상당히 큰 SPA의 일부이므로 추출하기 쉽지 않습니다. –

답변

3

실제 메모리 누수가 아닌 크롬에 대한 이상 함이 의심됩니다.

나는 최근에 같은 문제를 해결했습니다. IE11에서는 this.func = _.bind (this.func, this)를 메모리 누수로 표시하지만 Chrome은 수집 쓰레기 버튼을 100 번 누른 후에도이를 나타냅니다.

jsflag 넌센스로 크롬을 실행하고 기본 가비지 수집기를 노출하고 gc를 100 번 호출 한 후에도 표시됩니다.

실제로 Chrome에서 누출이 아닌 것을 증명하는 쉬운 방법은 브라우저에서 사소한 문제를 주요 문제로 만들고 엔진이 조치를 취하도록하는 것입니다. 할당 된 경계 기능이 같은 새로운 속성 할당 가진 인스턴스

:

= target.WhyAmILeaking를 새로운 배열 (200,000,000) .join ("YOURNOT");

크롬을 사용하여 세 가지 스냅 샷 기법을 수행하면 힙에있는 해당 문자열이 약 214MB로 클럭됩니다. 어떤 건설적인 행동 (두 번째 스냅 샷)을 다시하면 423MB로 이동하거나 214MB로 유지됩니다. 원본으로 214MB가 수집되었다는 것을 증명하는대로 작업이 완료되면 완료됩니다. 그것은 당신의 파괴적인 행동 (세 번째 스냅 샷)을하지 않으면 214mb로 돌아가서 원본이 수집되었음을 증명합니다.

423MB에 머무르면 누출이 있습니다.

아, 그리고 정확히 같은 상황 가로 질러 가난한 영혼의 또 다른 그룹 : https://github.com/jashkenas/backbone/issues/2269#issuecomment-13610969

TL; DR; 누수를 탐지하기 위해 IE 11을 사용하십시오.

1

나는 EcmaScript에서 클래스와,

클래스 메소드가있다 "이 바인딩"이 용어이 언급 한 "바인딩을이"이이 메서드 본문에 항상 클래스 인스턴스에 바인딩되는 경우 어떤에서 메서드에이 매개 변수가 실제로 전달되는 것과 관계없이 메서드의이 매개 변수가 무시됩니다. 이제 여기 예제에서

다음 어느 객체 것과 .. 나는이 누출되지 않은 경우라고해야 더 샘플 이렇게 주어진 스크립트 의문 특정 할 수 없다,

가없는 클래스 이 함수는 동일한 객체로 묶여 있으므로 클래스/객체가 존재할 때까지 쓰레기를 호출하지 않습니다. 부모 객체 (객체/클래스가 바인드 된) 범위가 끝난 후에 만 ​​가비지 수집됩니다.

이제 순환 참조가 완료되면 작업이 끝나게됩니다. >> 이것은 재귀 개념과 동일합니다 (개념은 같지만 같지 않음). 마지막 호출에서부터 시작됩니다. 역순으로 .. 가장 많은 호출 (최신 호출)이 먼저 릴리스 될 것입니다. .. 등등

코드는 함수를 바인딩하고 정의해서는 안되며 매번 재사용해서는 안되기 때문에 버그가 있어야합니다. 발자국이 메모리 풀의 브라우저 한계를 벗어날 때까지 잘 작동해야하고 누출해서는 안됩니다. 나는이 설명 바랍니다

..

1

당신이 개발자 도구를 사용하여 "강제 GC"을 트리거하고 있습니까? 그렇다면 개체가 그 다음 지속되면 위의 연구가 중요합니다.

개발자 도구를 통해 GC를 실행하지 않는 경우 GC 엔진이 작동하는 방식이 매우 복잡하며 세대 간 수집 개념 (2 세대 사용)이 있다는 것을 기억하십시오.

http://www.html5rocks.com/en/tutorials/memory/effectivemanagement/#toc-v8-gc

그것은 단순히 당신이 젊은 세대의 GC를 실행하는 데 필요한 임계 값에 도달하지 않았는지, 또는 오브젝트가 이전 세대에 있지만 오래된 세대 GC가 트리거되지 않을 것을 종신되었다고 할 수있다.

불행하게도 개발자 도구는 GC가 어떤 세대인지 보여주지 않는 것 같습니다.

관련 문제