2010-06-10 6 views
4

내 Flex 애플리케이션에서 약간의 메모리 누수 문제가 있습니다. 내 질문의 짧은 버전은 해당 객체에 대한 모든 활성 참조를 찾기위한 방법입니다 (AcitonScript 3)?Flex 객체 참조 표시

나는 Swiz를 사용하여 각자의 배후에있는 프리젠 테이션 모델을 가진 수많은 뷰를 보유하고 있습니다. 관심있는 뷰는 TabNavigator의 자식이므로 탭을 닫으면 뷰가 스테이지에서 제거됩니다. 뷰가 스테이지에서 제거되면 Swiz는 뷰의 모델 참조를 null로 설정합니다. 또한 View에서 RemoveAllChildren()을 제거합니다.

그러나 응용 프로그램을 프로파일 링 할 때이 작업을 수행하고 GC를 실행하면보기와 프리젠 테이션 모델이 모두 해제됩니다 (둘 다 서로에 대한 참조를 null로 설정 함). 뷰에서 사용하는 하나의 모델 객체 (발표자가 아니라)가 해제되므로 완전히 손상되지는 않습니다.

오늘은 프로파일 링을 시작한 지 얼마되지 않았습니다. (너무 일찍 최적화하지 않았다고 단단히 믿으므로) 어딘가에 떠 다니는 어떤 종류의 참조가 있다고 생각합니다.하지만 어디에서 도움이 될지 모르겠습니다. 목표 오브젝트를 참조하는 오브젝트 목록을 디버그하고 볼 수있는 기능. 이 모든 것이 가능한가? 네이티브가 아니라면, 이것을 디버깅 목적으로 미래의 앱에 코딩하는 가벼운 방법이 있는가?

건배.

답변

11

는 플렉스 빌더를 사용하고, 당신은 프로파일 러를 시도 할 수 있습니다. 필자의 경험으로 볼 때 성능을 프로파일 링하는 것은 좋지 않지만 메모리 누수를 찾는 데 큰 도움이되었습니다.

이 도구는 가장 직관적 인 도구는 아니며 익숙해지기까지 시간이 걸립니다. 실제로 실제로 도움이되는 시점까지 말입니다. 그러나, 제 의견으로는, 적어도 기본을 배우는 데 시간을 투자하는 것이 효과적입니다. 플레이어가 전역 적으로 사용하는 메모리 양 (System.totalMemory가 제공하는 것, 매우 거칠고 부정확하며 종종 오도 된 표시기)을 보는 것과 실제로 각 개체의 인스턴스 수를 추적하는 것, 실제로 얼마나 많은 개체가 있는지를 추적하는 것만 큼 엄청난 차이가 있습니다 살아 있고 어디에 할당했는지 (코드에서 누수 가능성을 발견하고 실제로 흑 마법에 의존하지 않고 수정할 수 있음).

저는 FB 프로파일 러에 대한 훌륭한 튜토리얼을 모르지만 어쩌면 시작하는 데 도움이 될 것입니다.

먼저 프로파일 러를 실행하십시오. 성능 프로파일 링을 선택 해제하고 다른 모든 것을 점검하십시오 (메모리 프로파일 링 사용, 실제 메모리 데이터보기 및 오브젝트 할당 스택 추적 생성).

프로필러가 시작되면 클래스별로 그룹화 된 앱 개체에 대한 통계가 표시됩니다.이 시점에서 필터를 조정할 수 있습니다. 많은 데이터를 볼 수 있으며 압도 당하기 쉽습니다. 지금은 가능한 한 플래시 및 플렉스 소재의 모든 것을 무시하고 수집해야한다고 생각하는 개체에 집중하십시오.

가장 중요한 수치는 "누적 인스턴스"및 "인스턴스"입니다. 첫 번째는 지금까지 생성 된 총 인스턴스 수입니다. 두 번째는 아직 살아있는 인스턴스의 수입니다. 따라서 좋은 출발점은 누수가 발생한 것으로 의심되는보기가 생성 된 상태로 앱을 가져 오는 것입니다. "누적 인스턴스"및 "인스턴스"에 대해 1이 표시되어야합니다.

이제이보기를 정리해야하는 지점 (예 : 앱의 다른 부분으로 이동)으로 이동하고 GC를 실행하십시오 (프로파일 러 UI에 해당 버튼이 있습니다) . 중요한 점은 앱 동작을 기대치와 비교하여 점검하는 것입니다. garbarge 수집 환경에서 자동으로 누수를 찾는 것은 정의에 의해 거의 불가능합니다. 그렇지 않으면 누출이 없을 것입니다. 그래서, 염두에 두십시오 : 당신은 당신의 기대에 대해 테스트합니다; 당신은 당신의 물건의 생명주기를 알고있는 사람입니다. "이 시점에서이 물건은 수집되어 있어야하고 그렇지 않다면 잘못된 것이 있습니다"라고 말할 수 있습니다.

이제보기의 "인스턴스"수가 0으로 내려 가면 누수가 없습니다. 앱이 누출되었다고 생각되면 적절하게 처리되지 않은 다른 개체를 찾으십시오. 개수가 1로 유지되면 뷰가 유출되었음을 의미합니다. 이제 이유와 위치를 찾아야 할 것입니다.

이 시점에서 "메모리 스냅 샷"(강제 GC 버튼 옆에있는 버튼)을 선택해야합니다. 스냅 샷을 열고 그리드에서 오브젝트를 찾아 두 번 클릭하십시오. 그러면이 객체에 대한 참조가있는 모든 객체의 목록이 표시됩니다. 실제로 나무이고 아마도 각 항목에 여러 개의 역 참조가 포함될 것입니다. 이것들은 당신의 시야가 수집되는 것을 방해하는 대상들입니다. 오른쪽 패널에서 또한 할당 추적을합니다. 이렇게하면 선택된 객체가 어떻게 생성되었는지 보여줍니다 (스택 추적과 거의 비슷 함).

아마 많은 수의 물체가 보일 것입니다. 그러나 가장 좋은 방법은 조사 대상 (보기)보다 긴 수명주기가있는 대상에 집중하는 것입니다. 내 말은 무대, 부모보기 등을 찾는 것입니다. 개체가보기에 의존하는 객체가 아니라보기가 종속되어있는 객체. 보기에 단추가 있고 단추에 청취자를 추가 한 경우 단추에보기가 표시됩니다. 대부분의 경우, 이것은 버튼이 뷰에 의존하고 뷰가 수집되면 버튼이기 때문에 이것은 문제가되지 않습니다. 그래서, 많은 사물들이 존재하기 때문에 초점을 유지하려고 노력해야합니다. 그렇지 않으면 아무 것도 얻지 못할 것입니다. 이 방법은 다소 경험적이지만 경험상으로는 효과적입니다.

누출 소스를 찾으면 소스로 돌아가서 적절하게 코드를 변경하십시오. (코드를 변경하는 것이 아니라 비트를 리팩토링해야 할 수도 있습니다). 그런 다음 프로세스를 반복하고 변경으로 인해 원하는 효과가 발생했는지 확인하십시오. 앱이 얼마나 크고 복잡한 지, 앱에 대해 얼마나 많이 알고 있는지에 따라 다소 시간이 걸릴 수 있습니다. 그러나 한 단계 씩 나아가서 한 번에 한 가지 문제를 찾아 해결하면 결국 누출을 제거 할 수 있습니다. 또는 적어도 최악의 경우와 더 명백한 것. 약간 지루한 동안, 그것은 돈을 지불합니다. (그리고 좋은 제쳐두고,이 지구상의 모든 이벤트 핸들러에 대해 약한 참조를 사용하는 대부분의 경우 시간 낭비를 결국 이해하게 될 것입니다. 단일 변수 등, 그것은 계몽적인 경험이다;).

희망이 도움이됩니다. 메모리 누수를 찾기위한도

+0

와우, 고마워. 메모리 스냅 샷을 두 번 클릭하면 정확히 내가했던 것입니다. 불행히도 시각화는 다소 복잡합니다. 나는 UIComponentDescriptors (부모 참조를 가진 자식이라고 생각 하는가?), 몇 개의 함수 (청취자를 나타내는 것처럼 보인다고?), Bindings 및 PropertyWatchers 등으로 구성된 22 개의 참조를 가지고 있지만 분명히 아무것도 아닙니다. * 다른 * 구성 요소. Function 항목 몇 개에 [listener1]과 같은 속성이있는 Button 하위 항목이 있으므로 MXML 정의에서 정의한 클릭 이벤트 리스너라고 추측합니다. – orlade

+0

우수 답변. 그것은 내 플렉스 애플리케이션 프로파일 링에 많은 도움이되었습니다. – Rajat

2

플래시 GC는 참조 횟수와 표시 및 스윕의 혼합을 사용하므로 순환 참조를 감지합니다. 오히려 당신은 개체 그래프에 다른 참조를 가지고있는 것 같습니다. 가장 일반적인 이유는 처리하려는 객체에 아직 처리되지 않은 객체에 이벤트 핸들러가 등록되어 있다는 것입니다. 처리기가 항상 약한 참조로 등록되도록 할 수 있습니다. 가능한 경우 모든 (기본) 클래스에서 addEventListener 및 removeEventListener를 재정의하여 등록 된 리스너와 제거되지 않을 가능성이 있는지 여부를 확인할 수도 있습니다.

또한 개체에 대한 소멸자를 작성할 수 있으며 UI 구성 요소는 그래픽을 지우고 모든 자식을 제거하고 모든 개체에 대해 모든 속성에 대한 참조를 제거 할 수 있습니다. 그렇게하면 개체 만 RAM에 보관되므로 많은 메모리 (20 B 정도의 작은 설치 공간, 변수 당 4 B (숫자의 경우 8))를 필요로하지 않아야합니다.

greetz
back2dos을 가정

+0

감사 back2dos. 모델을 강제적으로 분리하고, 모든 어린이를 삭제하고, (명백한) 청취자를 해제하기 위해 내보기의 dispose() 메소드를 넣으려고했지만 행운은 없었습니다.글쎄, 실제로는 좀 더 잘 작동한다고 생각합니다. (보기는 때로는 정리되지 않는 경우도 있지만) 누수가 지속됩니다. 오버라이드 (over)를 가진 뷰에서 addEventListener 호출을 추적했는데 (감사합니다), 9 개의 추가 (약함) 및 1 개의 제거가 있었기 때문에 거기에 뭔가있을 수 있습니다. 대부분 MXML 데이터 바인딩 ('created'및 'removed'제외)을 사용하므로 확실하지 않습니다. – orlade