성능개선

ㅎㄱㅎ·2020년 11월 20일
0

인트로

본인은 web 기반의 UI 에디터 솔루션을 담당하는 팀에 프론트엔드 개발자로 있습니다.
(html, webGL 둘다 함)

예전에 3D 관련해서 Vue에 Three.js Mesh가 속성으로 넘어가 reactive getter가 호출 되어 렌더링 프레임이 현저이 떨어져 이를 해결함으로써 프레임을 대폭 상승시켰는데요. 팀장님이 더 개선할게 없을지 알아보라는 명을 주셨습니다.

performance 찍어보기

애매할 때는 performance를 찍어보는게 참 좋은 방법 같습니다. 구조를 알고 js 지식이 있다면 performance 결과만 보고라도 어렴풋이 원인을 다양하게 유츄할 수 있기 때문 입니다.
확인하는 와중에 Performance에서 이상한 점을 발견 했습니다.

가장 왼쪽의 노란색 박스는 컴포넌트 로딩을 하는 영역 입니다. 저 밑으로 내려보면
컴포넌트 생성 라이프 사이클을 탑니다. 컴포넌트가 다 되면 그 다음 노란색 박스가 다음 로딩 과정 입니다.

근데 신기한 점은 그 다음 빨간색 박스 입니다.(1번)
여기서 호출되는 함수는 컴포넌트의 속성 업데이트 함수였습니다.
막대기 간격을 보아하니 하나 끝나면 다음게 되고 또 끝나면 그 다음게 되고 이렇게 되어 있는 것 같습니다. 굳이 이럴 필요가 있었을까요?

생성 하자마자 화면에 붙이고 속성 업데이트 진행 하면 될거 같은데요 왜 저렇게 나눠서 동작하도록 만들었을까요?

의심가는 것

setTimeout

가장 의심되는게 이거였습니다. 솔직히 개발하다 비동기 컨트롤을 잘못해 싱크가 잘 안맞으면 그냥 setTimeout(()=>{},0)으로 맞추면 되니까요

잘못된 코드

iterator를 하는데 대단히 잘못된 방법으로 작성 되었을 수도 있습니다.
콜백으로 다음->다음->다음 진행하는 것 처럼 말이죠
(이런 코드가 실제로 있었는데 이 부분은 아주 과거에 손을 봐뒀습니다. 그래서 후보로 등록)

recalculate style

jquery를 엄청 쓰는데,, 우리가 알다시피 DOM을 막 붙이고 그러면 브라우저 렌더링이 다시 일어나 스타일을 재계산 하는데 퍼포먼스를 쓰게 됩니다. 하지만 보라색이 로딩 단계에는 별로 없는것으로 보아 유력한 후보는 아닙니다.

범인

은 setTimeout이었습니다. 안에 덕지덕지 끼어 있네요. 이 부분을 해소 하니 아래와 같이 되었습니다.

컴포넌트 로딩 과정 뿐만 아니라, 다 로드하고 화면을 visibility: true 처리하는 곳에도
setTimeout으로 처리를 했는데 무려 callback이 async 함수이고 안에 await(...)도 있습니다. 이런거 가지고 스트레스 받아봐야 무슨 의미가 있겠습니까(이미 그 사람은 회사에 있지도 않고 ㅎㅎ..) 제 얼굴에 침뱉는거라고 생각하고 받아들입시다.. ㅎ

아래 코드 한번 보면.. timeEnd는 뭐라고 찍힐까요 300ms보다 많을까요 적을까요?

const promise = function(){
    return new Promise((resolve, rejct)=>{
        setTimeout(()=>{
            console.log("resolve")
            resolve(1)    
        }, 100)        
    })
}
console.time("set")
setTimeout(async ()=>{
    console.log("setTimeout")
    await promise();
    console.log("then")
    console.timeEnd("set")
}, 300)

console.time("set")
setTimeout(()=>{   
    console.timeEnd("set")
}, 300)

순서는 이렇습니다.
1 : setTimeout -> Task로 넘긴다
2 : 300ms 뒤에 setTimeout 콜백 호출
3 : console.log 호출
4 : await 만나면 event loop에서 promise 안에 setTimeout을 Task에 등록. resolve를 대기함
6 : 100ms뒤에 Promise resolve
7 : console.log, timeEnd print, setTimeout callback end

Promise가 resolve 될 때까지 시간만큼 넘어가는것을 알 수 있다..
이것까지 수정 하니 더욱 빨라졌다.(특수한 경우 아니면 이렇게까지 할 이유는 없다구 봅니당..)

개선 결과

간격이 사라졌습니다.. 첫번째 노란색 박스 안에서 컴포넌트 로딩, 속성 업데이트, DOM에 붙이기 다 하고 다음 단계로 넘어 가네요.

엄청난건 아니지만 효과가 있긴 있는 것 같다.. 자나깨나 비동기는 항시 신경써서.. 해야 될 것 같다!

profile
dog발자

0개의 댓글