scaleform.minarto.com

Loop 최적화 본문

Core

Loop 최적화

미나토 2012. 4. 19. 19:34


플래시는 컴파일이 없는 스크립트 언어입니다.

그렇기 때문에 런타임시에 코드 그대로 실행해버립니다... 컴파일 과정의 최적화가 없다는 뜻입니다.


그래서 그 최종 성능은 개발자의 역량에 따라 천차만별로 변할 수 있습니다.



가장 빠른 반복문에 대한 연구는 꽤 많습니다...

구글에 "반복문 최적화" 라고만 쳐도 굉장히 많은 양의 내용이 뜰겁니다.



참고로 이 내용은 제가 js 스터디를 하면서 알게된 내용입니다.

http://cafe.naver.com/wapp 이 카페를 참고하세요... (홍보 한번!!!!)



1. length 캐쉬


가장 많이 쓰이는 반복문인 for 문부터 보죠...


for(var i = 0; i<array.length; i++)


가장 흔한 형태의 코딩입니다만... 가장 느린 형태로 보면 됩니다.

일단 array.length 의 length 가 키검색값이 아닌 함수 콜입니다. 매번 순환될 때마다 함수콜을 한번씩 하는 셈입니다


for(var i = 0, c = array.length; i<c; i++)


length 를 캐쉬로 잡아놓으면 이것만으로도 꽤 많은 성능향상이 이루어집니다.



2. 전위연산자


그 다음 봐야할 것은 i++ 입니다. i++ 보다는 ++ i 처럼 전위 연산자로 처리하면 눈꼽만큼 좀 더 빠릅니다... :^)



3. while 역순환


다음의 코드가 혹시 익숙하신가요??


var i = array.length;

while(i --)


연산문과 조건문을 한번에 처리하게 되었고, 조건문 또한 0 을 바로 판별함으로서 조금 더 빨라지게 됩니다.

as2의 0 도 컴퓨터에서는 거짓으로 처리하기 때문입니다.



4. unrolling


저도 정확한 명칭은 이 글을 쓰게 되면서 알았는데요. 지금부터 소개할 방법이야 말로 이번 포스팅의 주제입니다.

앞선 내용들이야 검색하면 금방 나오는 놈들이고요...


원리에 대해서는 위의 단어로 구글 검색하면 많이 나올테니 전 바로 코드를 보겠습니다.


function loop($start:Number, $end:Number, $function:Function, $scope):Void { 

var l = $end - $start + 1;

if (l) {

switch(l % 8) { 

 case 7 : $function.call($scope, $start ++); 

 case 6 : $function.call($scope, $start ++); 

 case 5 : $function.call($scope, $start ++); 

 case 4 : $function.call($scope, $start ++); 

 case 3 : $function.call($scope, $start ++); 

 case 2 : $function.call($scope, $start ++); 

 case 1 : $function.call($scope, $start ++); 

 } 

 while ($start < $end) { 

 $function.call($scope, $start ++); 

 $function.call($scope, $start ++); 

 $function.call($scope, $start ++); 

 $function.call($scope, $start ++); 

 $function.call($scope, $start ++); 

 $function.call($scope, $start ++); 

 $function.call($scope, $start ++); 

 $function.call($scope, $start ++); 

 } 

 }

 }


자 완성된 반복문 유틸함수입니다.


실제 제가 사용하는 코드도 이것에다가 함수 인자를 받도록 처리한 것과 증감값을 넣을 수 있도록 한 것 이외에는 없습니다.


실 사용은 


loop(0, 100, f);

function f($index):void{

//trace($index);

}


뭐 이렇게 쓰면 되는거죠...


플래시(as2)로 돌려볼까요? 백만번 돌려보면 다음의 결과가 나옵니다.


테스트 코드는 다음과 같습니다.


var c:Number = 1000000;

var st:Number;


st = getTimer();

for(var i:Number = 0; i<=c; ++ i){

f(i);

}

trace(getTimer() - st);


st = getTimer();

loop(0, c, f);

trace(getTimer() - st);



for : 7479 ms

최적화 : 11877 ms


이런!!! 뭐야!!! 더 느려졌습니다. 이유가 뭘까요...(이건 저도 연구중...)



하지만 실망하긴 이릅니다.



이걸 스케일폼 플레이어(4.0.15)로 똑같이 백만번 돌려본 결과 다음의 결과가 나옵니다.

for : 4135 ms

최적화 : 3067 ms


무려 25% 정도의 향상이 이루어진답니다.



이정도의 성능향상이면 가독성을 좀 잃더라도 일부 적용해보는걸 고려해야하지 않을까요???





p.s. 똑같이 as3 도 백만번 돌려서 테스트 해보았습니다.


플래시 플레이어

for : 99 ms

최적화 : 103 ms


스케일폼

for : 1547 ms

최적화 : 1101 ms


플래시 플레이어는 최적화(jit 컴파일을 하는 것으로 알고 있습니다)가 일어나기 때문에 스케일폼에 비해 연산이 빠릅니다. 뭐 이건 어쩔 수 없죠...

렌더링의 강점을 얻었으니 만족해야 한달까요...??? (스케일폼은 멀티플랫폼 환경 지원 때문에 jit 컴파일을 지원하지 않습니다.)


암튼 as3 가 as2 보다 빠릅니다...


그리고 스케일폼으로 돌렸을시 최적화 반복문이 30% 이상 빠릅니다.



얼른 as3 쪽이 안정화되길 바랍니다~~~