Firefox 4: 프레임 지연 생성(Lazy Frame Construction)으로 더 좋은 성능내기

이 글은 Timothy Nikkel의 블로그에서 퍼온 글입니다.

프레임 지연 생성(Lazy Frame Construction)은 Gecko에 새롭게 추가된 기능으로 많은 DOM관련 기능 동작(appendChild, insertBefore, etc)시 레이아웃을 즉시 재배치하지 않도록 합니다. 이 기능은 매우 복잡한 웹페이지의 인터랙티브 성능을 엄청나게 향상시킬 수 있습니다. 만약 이를 확인해 보기 원한다면 Firefox Nightly를 다운받으시기 바랍니다.

프레임 지연 생성은 최근에 mozilla-central 저장소에 포함되어졌습니다. 이 기능이 무엇이고 어떻게 성능을 향상시키는지 설명하기 위해서 약간의 배경 지식이 필요합니다. 웹 페이지의 DOM 트리의 각 노드들은 그 노드가 페이지의 어디에 얼마의 크기로 그려질지를 결정하는데 사용되어 지는 프레임(frame)이라는 것을 가지고 있습니다. 이 프레임은 CSS 스펙의 박스와 그 컨셉이 매우 유사합니다. 지금까지는 프레임이 각 DOM 노드마다 열심히 만들어졌는데요 . 이말인 즉슨 노드가 다큐먼트에 추가되자 마자 바로 바로 프레임을 생성한다는 것입니다. 그러나 이것은 여러 상황에서 쓸모없는 일만 만들 수 있습니다. 예를 들어 스크립트가 DOM에 많은 수의 노드를 추가한다면 노드가 추가될때마다 각 노드마다 프레임을 만들 것입니다. 그러나 프레임 지연 생성을 사용할 경우 한번에 모든 노드를 처리할 수 있으며 이로 인해 오버헤드를 줄일 수 있습니다. 또한 프레임이 생성되는데 걸리는 시간으로 인해 더이상 스크립트를 중단 시키는 일은 없으므로 스크립트는 계속 자신의 할 일을 하고 프레임은 필요한 시점에 생성될 것입니다. 스크립트가 다큐먼트에 노드를 바로 추가하거나 삭제하는 다른 경우가 있어도 그것들이 화면에 표시되어질 일이 없을 경우 프레임을 생성할 필요는 전혀 없습니다.

다큐먼트에 노드가 추가될 경우 노드는 프레임이 만들어질 필요가 있다는 플레그를 세팅하고 다음번에 리프레쉬 드라이버(refresh driver)에 의해 프레임이 생성되었다고 알려줍니다. (현재는 20ms 간격으로). 리프레쉬 드라이버는 웹페이지, CSS, SVG 애니메이션를 재배치하는 역할을 합니다.

프레임 지연 생성을 사용한 다음 두 예제를 보시죠.

이 예제는 80000개의 div 요소를 추가하고 스크립트에 의해 변경된 것이 적용되고 유저에게 보여지기 전까지 얼마의 시간이 걸리는지를 알아보기 위해 보류되었던 레이아웃을 모두 처리하도록 합니다. 스크립트는 레이아웃 재배치를 하지 않도록 하고도 계속해서 실행이 가능하나 실제 이와같은 동작이 얼마나 걸리는지를 알아보기 위해 이렇게 하였습니다.

var stime = new Date();
var container = document.getElementById("container");
var lastchild = document.getElementById("lastchild");
for (var i = 0; i < 80000; i++) {
  var div = document.createElement("div");
  container.insertBefore(div, lastchild);
}
document.documentElement.offsetLeft; // flush layout
var now = new Date();
var millisecondselapsed = (now.getTime() - stime.getTime());

프레임 지연 생성을 사용할 경우 80000번의 각각 다른 노드 추가에 대한 오버헤드를 줄이고 단 한번의 실행으로 80000개의 div 요소를 추가할 수 있습니다. 프레임 지연 생성을 사용하지 않을 경우 평균 1358 ms이 걸린데 반해 프레임 지연 생성을 사용할 경우 777 ms이 걸렸습니다.

다음 예제는 실제 웹페이지에서 사용되던 것입니다. div 노드를 추가하고 다음과 같이 세팅을 합니다. “div.style.position = ‘absolute’;”. 이렇게 2000번을 반복한 후 스크립트에 의해 변경된 것들이 적용되고 유저에게 보여지기 전까지 얼마의 시간이 걸리는지를 알아보기 위해 보류되었던 레이아웃을 모두 처리하도록 합니다.

var stime = new Date();
var container = document.getElementById("container2");
for (var i = 0; i < 2000; i++) {
  var div = document.createElement("div");
  container.appendChild(div);
  div.style.position = "absolute";
}
document.documentElement.offsetLeft; // flush layout
var now = new Date();
var millisecondselapsed = (now.getTime() - stime.getTime());

프레임 지연 생성을 사용할 경우 위치를 절대값으로 설정 한 후까지도 div의 프레임 생성으로 인한 방해를 받지 않으므로 이로 인한 어떤 수고도 낭비를 하지 않습니다. 프레임 지연 생성을 사용할 경우 평균 4730 ms이 걸렸으나 프레임 지연 생성을 사용할 경우 130 ms이 걸렸습니다.

작성자: Banseok Ahn

Banseok Ahn가 작성한 문서들…


댓글이 없습니다.

댓글 쓰기