HTML/JAVASCRIPT 2007/11/09 12:29
그동안 Prototype 자바스크립트 프레임웍의 사용법을 익히느라 필요이상으로 무리하게 사용해 왔습니다. 간단하게 크로스 브라우징이 보장되며 코드를 아름답게(?) 만들 수 있다는 장점 때문이였는데요. 개발하기 편하여 생산성 높은 환경을 제공하는 반면 원시코드에 비해 9배이상의 시스템 성능저하가 나타나기도 합니다. 아래와 같은 테스트용 루프 함수를 만들고 결과는 동일하면서 모든 브라우저에서 통용되며 상습적으로 사용되는 Prototype함수와 자바스크립트 메서드를 벤치마킹해 보았습니다. 테스트에 사용된 Prototype 프레임웍 라이브러리의 버전은 Scriptaculous1.6.1에 포함된 1.5.0_rc0이며, 브라우저는 파이어폭스2.0b, 시스템사양은 Pentium4, 3.00GHz입니다.
1. DOM 엘리먼트 스타일 설정:
프로토 타입에서는 여러가지 형태로 DOM을 주무를수 있게 해 주는데요. 1만회에 걸쳐 객체를 width:'300px', height:'100px'으로 변경하는 테스트입니다. 아래의 결과를 살펴봅시다.
동일한 결과값을 가지는 위 4가지 코드는 처리에 필요한 시간이 서로 다릅니다. 4번은 원시코드와 2배이상 차이가 벌어지는 재미있는 결과를 보여줍니다. 반복성이 짙은 경우, 즉 엘리먼트를 실시간으로 업데이트하거나 모션에 사용할 코드는 4번의 형태는 가급적 피하는 것이 좋습니다. 당연히 1.번이나 2번의 형태가 좋겠죠?
2. DOM 엘리먼트 스타일 값 구하기:
DOM의 위치또는 모양을 확인하기 위해 prototype은 getStyle, getDimensions 메서드를 제공하고 있으며, 엘리먼트의 높이 값만을 구하기 위한 getHeight와 같은 메서드도 있습니다.(그나저나 getWidht는 왜 없는걸까요?) 엘리먼트의 높이값(height)을 알기위한 가장 빠른 방법은 무엇인지 살펴 봅시다.
높이 값이 '123px'와 같은 스트링으로 반환된 6, 7번은 'px' 문자열을 없애기 위해 parseInt()하거나 '스트링.substring(0,스트링.length-2)'을 사용해야 합니다. 6, 7번은 쓸일이 없을 것 같은데 왜 집어넣었냐구요? 하지만 아래와 같은 경우(다중 이미지 비율계산)에는 벤치마크 결과와는 정 반대로 6, 7번이 훨씬 빠른 성능을 내기도 합니다.(슬라이드를 움직여 프레임을 비교해보세요.)
Element.getHeight('엘리먼트')
Width: 75px
Element.getStylet('엘리먼트', 'height')
Width: 75px
3. DOM 엘리먼트.Show/Hide:
또한 가장 많이 사용하는 것 중의 하나인 엘리먼트 Show/Hide를 봅시다. 1만회를 루프로 돌린 결과입니다. 스타일의 결과와 비슷하지요? 역시 원시코드가 가장빠릅니다. 하지만 이것은 결과값이 브라우저에 따라 서로 다르게 나타나기도 합니다. IE에서는 $('element').style.display = 'block', 파이어폭스에서는 Element.show('element')가 잘 돌아간다는 느낌입니다.
4. DOM 엘리먼트.InnerHTML:
이것은 3천회 루프의 결과입니다. 이 또한 원시코드를 사용하는 것이 3배 빠르군요. 눈치 채셨겠지만 "오브젝트.메서드"의 결합과 "메서드(오브젝트)"에도 결과는 같지만 소요시간이 다릅니다. DOM 스타일링에는 메서드(오브젝트)와 같은 형태가 좋습니다. 뭐 결과적으로는 원시코드를 적절히 혼용하면 시스템 퍼포먼스를 크게 끌어올릴 수 있다는 것이지만요.
5. 정수 구하기:
소수점 이하의 수를 반올림하는 경우 100만회 루프 결과 toFixed(0) 보다 Math.round()가 2배이상 빠릅니다.
6. 브라우저별 색상처리:
좀 다른 얘기지만, getStyle로 색상 값에 따른 이벤트를 처리하는 경우 브라우저 마다 가져오는 색상 값이 틀립니다. 스타일스트(CSS)에 '#f80'으로 설정되었을 경우 브라우저별로 가지고 온 결과는 아래와 같습니다.
7. 홀수 짝수 구하기:
홀수나 짝수를 루프에서 처리할 때 'n%2'를 쓰거나 'n&1'을 쓰는 두가지 방법이 있습니다. 이럴땐 'n&1'이 미약하게 나마 약간 더 빠릅니다.
추가. 문자열비교 : match 보다 test가 빠르고 indexOf가 두배 빠름(50만회)
추가. if문과 단순 조건문 속도차이 없음.(500만회)
추가. DOM Selecter(500회)
// 타임체크 함수
function timeChecker() {
var befor, loops, after, tpo, tet, result
before = new Date()
loops = 500 //루프 수
for (var i=0; i < loops; i++) {
Element.update('element', '내용')// 태스트함수
}
after = new Date()
tpo = Math.round(1000*(after-before)/loops)
tet = (after-before)/1000
result = 'Time per operation: '+tpo+', Total excuted time: '+tet; //결과값
throw(result)
//return result
}
timeChecker();
1. DOM 엘리먼트 스타일 설정:
프로토 타입에서는 여러가지 형태로 DOM을 주무를수 있게 해 주는데요. 1만회에 걸쳐 객체를 width:'300px', height:'100px'으로 변경하는 테스트입니다. 아래의 결과를 살펴봅시다.
1. document.getElementById('엘리먼트').style.스타일 = '값' // (원시코드, 2라인) --> 1.14초
2. $('엘리먼트').style.스타일 = '값' // (2라인) --> 1.656초
3. Element.setStyle('엘리먼트', {'스타일:값의 배열x2'}) // --> 1.985초
4. $('엘리먼트').setStyle({'스타일:값의 배열x2'}) // --> 3.047초
동일한 결과값을 가지는 위 4가지 코드는 처리에 필요한 시간이 서로 다릅니다. 4번은 원시코드와 2배이상 차이가 벌어지는 재미있는 결과를 보여줍니다. 반복성이 짙은 경우, 즉 엘리먼트를 실시간으로 업데이트하거나 모션에 사용할 코드는 4번의 형태는 가급적 피하는 것이 좋습니다. 당연히 1.번이나 2번의 형태가 좋겠죠?
2. DOM 엘리먼트 스타일 값 구하기:
DOM의 위치또는 모양을 확인하기 위해 prototype은 getStyle, getDimensions 메서드를 제공하고 있으며, 엘리먼트의 높이 값만을 구하기 위한 getHeight와 같은 메서드도 있습니다.(그나저나 getWidht는 왜 없는걸까요?) 엘리먼트의 높이값(height)을 알기위한 가장 빠른 방법은 무엇인지 살펴 봅시다.
1. document.getElementById('엘리먼트').offsetHeight // (원시코드) --> Number 0.391초
2. $('엘리먼트').offsetHeight //Number --> 0.625초
3. Element.getHeight('엘리먼트') //Number --> 0.641초
4. document.getElementById('엘리먼트').getHeight() //Number --> 1.328초
5. $('엘리먼트').getHeight() //Number --> 1.563초
6. Element.getStyle('엘리먼트', '스타일') //String --> 2.812초
7. $('엘리먼트').getStyle('스타일') //String --> 3.843초
높이 값이 '123px'와 같은 스트링으로 반환된 6, 7번은 'px' 문자열을 없애기 위해 parseInt()하거나 '스트링.substring(0,스트링.length-2)'을 사용해야 합니다. 6, 7번은 쓸일이 없을 것 같은데 왜 집어넣었냐구요? 하지만 아래와 같은 경우(다중 이미지 비율계산)에는 벤치마크 결과와는 정 반대로 6, 7번이 훨씬 빠른 성능을 내기도 합니다.(슬라이드를 움직여 프레임을 비교해보세요.)
// Realtime image Ratio
function setRatio(v) {
var x,y,h
var w=Math.round(v)
$$('array').each(function(e){
x=Element.getStyle(e, 'width'); y=Element.getStyle(e, 'height')
h=Math.round(v*y.substring(0,y.length-2)/x.substring(0,x.length-2));
e.style.width=w+'px'
e.style.height=h+'px'
e.style.margin=(w-h)/10+'px'
})
}
Element.getHeight('엘리먼트')
Width: 75px
Element.getStylet('엘리먼트', 'height')
Width: 75px
3. DOM 엘리먼트.Show/Hide:
1. document.getElementById('엘리먼트').style.display = 'block' // --> 0.547초
2. $('엘리먼트').style.display = 'block' // --> 0.812초
3. Element.show('엘리먼트') // --> 1.312초
4. $('엘리먼트').show() // --> 2.609초
또한 가장 많이 사용하는 것 중의 하나인 엘리먼트 Show/Hide를 봅시다. 1만회를 루프로 돌린 결과입니다. 스타일의 결과와 비슷하지요? 역시 원시코드가 가장빠릅니다. 하지만 이것은 결과값이 브라우저에 따라 서로 다르게 나타나기도 합니다. IE에서는 $('element').style.display = 'block', 파이어폭스에서는 Element.show('element')가 잘 돌아간다는 느낌입니다.
4. DOM 엘리먼트.InnerHTML:
1. document.getElementById('엘리먼트').innerHTML // --> 0.672초
2. $('엘리먼트').innerHTML = '내용' // --> 0.766초
3. Element.update('엘리먼트', '내용') // --> 2.39초
이것은 3천회 루프의 결과입니다. 이 또한 원시코드를 사용하는 것이 3배 빠르군요. 눈치 채셨겠지만 "오브젝트.메서드"의 결합과 "메서드(오브젝트)"에도 결과는 같지만 소요시간이 다릅니다. DOM 스타일링에는 메서드(오브젝트)와 같은 형태가 좋습니다. 뭐 결과적으로는 원시코드를 적절히 혼용하면 시스템 퍼포먼스를 크게 끌어올릴 수 있다는 것이지만요.
5. 정수 구하기:
1. Math.round(넘버) // --> 1.453초
2. (넘버).toFixed(0) // --> 3.859초
소수점 이하의 수를 반올림하는 경우 100만회 루프 결과 toFixed(0) 보다 Math.round()가 2배이상 빠릅니다.
6. 브라우저별 색상처리:
좀 다른 얘기지만, getStyle로 색상 값에 따른 이벤트를 처리하는 경우 브라우저 마다 가져오는 색상 값이 틀립니다. 스타일스트(CSS)에 '#f80'으로 설정되었을 경우 브라우저별로 가지고 온 결과는 아래와 같습니다.
오페라 = '#ff8800'
파이어폭스 = 'rgb(255, 136, 0)'
익스플로러 = '#f80'
7. 홀수 짝수 구하기:
홀수나 짝수를 루프에서 처리할 때 'n%2'를 쓰거나 'n&1'을 쓰는 두가지 방법이 있습니다. 이럴땐 'n&1'이 미약하게 나마 약간 더 빠릅니다.
for (var n=0; n < 100;n++) if(n%2==1)$('element').innerHTML = 'test';
for (var n=0; n < 100;n++) if(n&1==1)$('element').innerHTML = 'test';
추가. 문자열비교 : match 보다 test가 빠르고 indexOf가 두배 빠름(50만회)
var testing = 'test test test';
testing.match(/test/); // --> 0.702초
/test/.test(testing); // --> 0.643초
testing .indexOf('test ') != -1; // --> 0.395초
추가. if문과 단순 조건문 속도차이 없음.(500만회)
var boo = true;
boo = boo? 'true' : 'false'; // --> 0.736초
if(boo){ boo = 'true'; } else { boo = 'false'; } // --> 0.726초
추가. DOM Selecter(500회)
$$('#taglist .row');// --> 1.496초
$$('.row');// --> tset failed
document.getElementsByClassName('row', 'taglist');// --> 0.193초
document.getElementsByClassName('row');// --> 3.321초
이 글에는 트랙백을 보낼 수 없습니다
0