본문 바로가기
FLEX 공유/FLEX 자료공유

플래쉬플레이어9 자원 관리(Resource management)

by 반화넬 2008. 2. 14.
반응형

Resource management strategies in Flash Player 9

 

원문 싸이트

http://www.adobe.com/devnet/flashplayer/articles/resource_management.html

 

번역 by 노리노리

 

..인사글 생략...

 

AS3.0에서 자원관리에 영향을 주는 가장 큰 변화는 새로운 diplay list model이다.

 

플레쉬 플레이어 8(혹은 그 이전)에서는디스플레이 객체가 화면에서 제거되면

(using removeMovie or unloadMovie), 디스플레이객체와 그것에 연관된 모든것들은 즉시 메모리에서 삭제되고 코드 실행을 중지했다.

 플래쉬플레이어 9은 디스플레이 객체들(sprites, movieclips, etc.)이 보통의 객체들과

같은 방식으로 보내지는 훨씬 유동적인 디스플레이 리스트 모델을 소개한다.

 

이것은 개발자들이 재할당(moving a display object fromone display list to another)이나

SWF에서 로드된 디스플레이 객체들의 변수화 등과 같은 쿨~한 것들을 할 수있다는 얘기다.

 

불행하게도, 이것은 지금 흥미로운 이슈가(아마 그렇지 않을지도)되고있는 디스플레이 객체들이 가비지 콜렉터에의해정리되는 보통의 객체들과 같은 방식으로도 정리된다는 것을 의미한다.

 

 

----왜 자원관리가 이슈가 되는가?---------

 

플래쉬 개발자들은 AS3.0에서 새로운 자원관리고찰에 대해 보고 있고그 컨셉이 복잡하다고 생각하는 것 같다. 반면에, 자바 개발자들은아마 관심도 없을 것이다.

왜 이런지 이해할 수가 없는가 : 플래쉬 개발자들은 더이상 필요하지않은 참조들을 죽이는것과 같은 자원관리방식을 향상시키는데 익숙하지 못하다. 반면 자바 개발자들은 이런것들을전부터 생각해왔다.

 

이런 이슈들은 거의 모든 근대 메모리 관리 언어들에게는 늘 그렇다. 불행하게도, 그걸 피할길이 없는것이다.

 

 

 

자원관리는 인생의 진실임에도 불구, 플래쉬는 가끔 다른 언어들(Flex를포함)까지 끌어들여 그 문제를 야기시킨다.

플래쉬 컨텐트는 수많은 쓸데없는 것들을 포함해야만 하거나 코드실행에 반응해야만 한다

-자바와 플렉스가 대부분 내부동작인-집약-CPU 코드가 주로 유저 인터페이스에서만 실행되는-것과는 다르다.

게다가, 플래쉬 프로젝트는third-party 소스로부터(아마 허접한 코딩 스탠다드..)

외부 컨텐트를 다른 플랫폼들 보다 훨씬 자주, 많이 불러와야만 한다.

플래쉬 개발자들은 또한 툴,프로 파일러, 그리고 설정할 프레임워크들도 별로 갖고있지않다.

 

결국, 플래쉬 개발자들은 일반적으로 정석 프로그래밍의 배경지식에서훨씬 뒤떨어진다는 것이다.

대부분의 내가 아는 플래쉬 개발자들은 음악,예술,영업,철학 또는 프로그램과는 동떨어진것에 대해 해박하다.

이런 상이함이 실제로 자원관리 문제에 대해서는 조율하지 못하면서도 정말 환상적인 창작물과 콘텐트 아이디어를 내놓는다.

 

 

이슈1:Dynamic Content

 

자원관리에 있어서 더 주목되는 것 중에 하나는 당신이 다이내믹하게 인스턴스화 하고 또 나중에 지울 수도 있는 sprites(혹은 다른 display object)와 관련이 있다.

Display object들은 당신이 Stage에서 remove한다해도 메모리에는 계속해서 남아있는다. 왜냐면, 그들은 더이상display list에서 죽거나 살거나 하지 않기 때문이다.

clip(그것의 리쓰너들을 다 포함해서)을 참조하는(연결되어있는) 다른모든 레퍼런스들을 완전히 지우지 않는한, clip은 아마 절대 제거되지 않을것이다. 혹시나 아주 처리를 잘해서 모든 레퍼런스들을 제거하는데 성공했다면, clip은다음에 가비지 콜렉터가 돌아올때(, 사용중인 메모리에서언제 돌아올지모를 어중간한 지점에) 메모리에서 삭제될 것이다.

 

 

이건 정말 정말 중요하다! 디스플레이 객체가 메모리에 계속 남는것뿐만 아니라, timer, enterFrames, 이미 범위에서 벗어난 listener들과 같은 다른 여러 "쓰잘데기 없는" 코드를 계속 실행하고 있다는 것은 꼭 알아둬라.

 

 

 

 

이것에 대해 도움이 될만한 예들:

 

1. 자신의 enterFrameevent에 동참하는 Game sprite. 프레임마다 그것은 움직이고, 어플리케이션은 그것들에 근접한 다른 게임 요소들을 결정하기 위한 몇가지 계산을 실행한다.

AS3.0에서는, 디스플레이리스트에서 그 sprite를 제거하고 모든 레퍼런스들을 널로 한다고 해도, 어플리케이션은 가비지콜렉터가 와서 제거된 sprite를 청소할때까지계속 그 계산들을 실행할것이다.

sprite가 제거될 때 반드시enterFrame listener도 확실히 제거할 것을 명심하라.

 

2. Stage mouseMoveevent에 동참하는 마우스를 따라다가는(새 이벤트 모델에서 이런 취지를 볼수 있는 방법이요거뿐이다)  movie clip을생각해보자. 리쓰너를 제거하는걸 기억하지 않는 한, clip은마우스가 움직일 때 마다 코드를 실행할 것이다.

클립이 지워졌다고 해도 말이다. event dispatch를 위해그것과의 연결이 Stage에서 계속 존재하기 때문에 클립은 영원히 코드를

실행한다. 이걸 어떻게 해결하면 좋을지는 나중에 의논해보겠다.

 

 

이제 가비지 콜랙터가 여러 sprite들을 가져가기 전에 그것들을인스턴스화하는것과 제거하는것의 연관성을 상상해보자. 혹은 sprite의 모든 레퍼런스들을 제거하는데 실패한것을.

의도하지 않게 CPU의 자원이 한계를 쉽게 넘어버릴수(당신의 어플리케이션이나 게임이 느려지거나 뻑나는, 혹은 피씨가 완전다운되는 일까지..)있을 것이다.

현재 플래쉬 플레이어에서 실행되고있는 디스플레이 객체를 죽이거나 멈추는 방법은 없다.

플래쉬 개발자들이 그 객체들을 디스플레이에서 얼마나 잘 제거하느냐에 달려있는 것이다.

 

 

 

 

이슈 2: Loaded content

 

 

로드된 SWF들의 컨텐츠는 다른 객체들이 불려지는 것과 같은 방식으로처리되는 것을 기억하라,

로드된 컨텐트들에 어떤 문제들이 일어나수있는지 상상할수 있을것이다.

다른 디스플레이 객체들과 비슷하게, 로드된 SWF와 그것의 컨텐츠들을 메모리에서 완벽히 제거하거나 실행중 멈추게 하는 방법은 없다.

 

Loader.unload 를 실행하면 간단히 SWF의 레퍼런스들을 널로 할수있다; 이것 역시 다음 가비지 콜랙터가와서 비울때까지 계속해서 실행하고 있을것이다.(연결된 다른 레퍼런스들까지 모두 제거되었다고 가정하에)

 

아래 두가지 시나리오를 생각해보자:

 

1. 당신은 시범적인 플레쉬 프로젝트들을 불러오는 뼈대를 만들었다. 이 것들은 잘게 쪼게져 제한된 CPU의 자원으로 들어간다.

  유저는버튼을 클릭함으로 한개를 불러오고, 그것을 보여주고, 또한번클릭으로 두번째를 불러온다.

  첫번째 객체에 연결된 모든 참조들이 깨끗하게 제거되었다고 한다해도, 두번째 객체가 시작되면서 같은 시간에프로세서가 한계를 넘어서도록 그들은 뒤에서 계속 실행되고 있다.

 

2. 고객이 당신에게 다른 개발자들에 의해 만들어진 AS3.0 SWF들을 로드하는 어플리케이션은 만들어달라고 했다.

   이개발자들은 Stage에 리쓰너를 집어넣거나 반대로 그것들의 컨텐트를 참조하는 외부 레퍼런스들을 만들기도한다.

  왜냐면그들의 컨텐트를 unload할 방법이 없기 때문이다. 아마이것들은 유저가 당신의 어플리케이션을 종료할때까지 계속 메모리에 남아서 실행되고 있을것이다. 로드된컨텐트가 아무 외적인 레퍼런스를 가지고 있지 않다고 해도 다음 가비지콜렉터가 올때까지 독립적으로 실행하고 있을것이다.

 

 

당신이 신용하기 힘든 컨텐트들을 로드해야할 어플리케이션을 디자인 할때, 코드들은당신이 unload한 이후에도 계속 실행하고 있을수 있다는 것은 아주 신중히 고려해야할 중요한 문제이다. 이런 컨텐트들이 적합한 Flash Player security model에의해 실행된다고 하더라도, 당신의 어플리케이션이 개발되는 동안 잠재된 취약점이 있다는것을 고려하는것은아주 좋은 자세이다.

 

---------------------

System.totalMemory 사용

 

System.totalMemory가 간단한 툴이긴 하지만, 개발자들이 플래쉬에서 사용할수 있는, 런타임시 맨 처음 마크되는검사 툴로 아주 중요한 것이다.

이것은 당신이 런타임시 플래쉬 플래이어가 얼마만큼 메모리를 사용하고 있는지 볼수있게 해준다.

당신은 시스템 모니터를 사용하지 않아도 개발하는 동안 당신의 작업을 검사할수 있게된다.

더 중요한것은, 당신의 컨텐트들이 당신의 고객들에게 심각한 문제를안겨주기 전에 메모리누수문제에 대해 선조취 할 수 있도록 해준다는 것이다.

이것은 error throw하는것보다도, 그리고 당신의 어플리케이션에 대해서도 좋은 것이며,

사용자의 시스템이 수렁에 빠지거나 아예 먹통이 되어 버리는 일에 대해서는 더욱 그러할것이다.

 

어떻게 사용하는지 간단한 예를 보자:

 

import flash.system.System;

import flash.net.navigateToURL;

import flash.net.URLRequest;

...

// check our memory every 1 second:

var checkMemoryIntervalID:uint =setInterval(checkMemoryUsage,1000);

...

var showWarning:Boolean = true;

var warningMemory:uint = 1000*1000*500;

var abortMemory:uint = 1000*1000*625;

...

function checkMemoryUsage() {

   if(System.totalMemory > warningMemory && showWarning) {

     // show an error to the user warning them that we're running out ofmemory and might quit

     // try to free up memory if possible

     showWarning = false; // so we don't show an error every second

    }else if (System.totalMemory > abortMemory) {

     // save current user data to an LSO for recovery later?

     abort();

    }

}

function abort() {

   //send the user to a page explaining what happpened:

  navigateToURL(new URLRequest("memoryError.html"));

}

--------------------------------------------------------

 

이것은 여러가지 방법으로 강화될수도 있겠지만, 이 코드는 프로세스이면의 기본적인 발상(구성)을 말하는데 충분하리라 본다.

 

totalMemory는 한개의 프로세스에서 공유되는 값임을 반드시명심하라!

한개의 프로세스란 브라우저나, OS, 어떻게 창들이 열렸는지에 따라단지 하나의 브라우져윈도우가 될수도 있고, 열려있는 모든 윈도우가 될수도있다.

 

예를들어, MS Windows에서 프로세스와 값들이 엄청나게 꼬여있는것에반해, Mac OS X에서는 모든 사파리 브라우져 창들은 한개의 프로세스와 totalMemory를 공유한다.

 

---------------------------------

Weak references

---------------------------------

내가 AS3.0에서 볼 수 있게되어 정말 행복했던 것 중 하나는 바로 Weak reference들이다.

이것들은 레퍼런스들을 가비지 콜렉터가 모을수있는 객체의 능력인collection처럼 인식하게 해준다.

만약 레퍼런스들이 weak객체로 각인되기만 한다면, 이것들은 가비지콜랙터가 다음에 올때 제거될수 있을것이다.

 

불행하게도, weak references는 단지 두가지 환경에서만지원이 된다.

첫째는 아주 훌륭한(가비지 콜렉션에서 가장 많이 문제를 야기시키는가장 일반적인 레퍼런스이기에) 이벤트 리쓰너들이다.

리쓰너들을 사용할때 언... weak reference를 사용할것을 강추!한다.

이것은 단지 addEventListener()를 콜할때 다섯번째 파라메터값을 true로 주는것 만으로 해결된다. 아래처럼..

-------------

someObj.addEventListener("eventName",listenerFunction,useCapture,priority,weakReference);

stage.addEventListener(Event.CLICK,handleClick,false,0,true);

// the reference back to handleClick (andthis object) will be weak.

 

 

이것을 더 알고싶거들랑, 아래 참고~

http://www.gskinner.com/blog/archives/2006/07/as3_weakly_refe.html

 

----------------

앞으로 갈 길

----------------

자원 관리는 AS3.0개발에 있어 아주 중요한 부분이다. 이걸 무시한다면 쓰레기같은 컨텐트만 나오게 될것이다.

게다가 사용자의 시스템까지 잠재적으로 완전히 도둑질하는 위험까지 있다.

더 이상의 디스플레이 객체를 메모리에서 완벽히 지우거나 실행중인코드를 멈추는 방법은 없다.

(말인즉, 모든 플래쉬개발자는 어플리케이션에서 더이상 사용하지 않는 객체들을 깨끗히 제거할 책임이 있다는말이다)

 

AS3.0은 작업의 양이 충분히 증가되어 온 동안 개발자들은 자신의어플리케이션의 자원관리를 반드시 해야하며, 메모리사용을 관리하는데 도움을 주는 새로운 툴들이 플래쉬플레이어 9에 들어있다.

이 새로운 툴들의 효율적인 전략과 접근을 잘 합해서 (내 강의의 주제중, Understanding garbage collection in Flash Player 9 는당신이 플래쉬와 플렉스 프로젝트에서 성공적으로 자원을 관리하도록 해줄 것이다.)

 

 

Understanding garbage collection in FlashPlayer 9는 해석중이니 완료되는대로 배포하겠습니다. (__)

반응형