CSS Paint Times and Page Render Weight

HTML5 Rocks

주의:이 글은 브라우저의 특정 버전의 수치적인 평가를 포함하고 있습니다. 시간이 지나면 여기에서 제공될 데이터로써의 이러한 수치는 변경될 것입니다.

소개

만약 여러분이 브라우저는 어떻게 동작하는가와 같은 것들을 알고 있는 타입의 사람이라면 크롬의 GPU 가속 렌더러/컴포지트 동작에 대한 자세한 최근의 몇가지 놀라운 글들을 이미 알고 있을 것입니다. 일단 크롬에서의 렌더링 가속: 레이어 모델은 크롬이 페이지의 출력을 위해 레이어 개념을 어떻게 사용하는지 훌륭하게 소개하고 있으며 더 깊이 들어가보자면 크롬의 GPU 가속 합성(Composition)은 크롬이 페이지 렌더링을 위해 GPU와 함께 이러한 레이어들을 어떻게 사용하는지에 대해 논의합니다.

이러한 글들을 요약하자면 크롬에서의 하드웨어 가속 경로는 여러분의 페이지를 페이지의 시각적요소를 레스터화하여 타일들로 출력(Paint)할 것입니다. 그 뒤에 이러한 타일들은 스크린에 타일들을 합성(Compositing)으로 알려진 과정인 최종 출력을 위해 GPU로 전달됩니다. 크롬은 필요성과 플랫폼에 따라 변경이 가능한 경험적 성능에 기반하여 메모리 안으로 밖으로 타일들을 이동합니다.

철학적인 질문

3D를 위한 소프트웨어 래스터라이져(software rasterizers)를 작성하는데 시간을 많이 들이는 것은 몇가지 CSS 속성들이 페이지를 그릴 때 성능을 다르게 만들 것이라는 분명한 믿음이 있습니다. 예를 들어 작은 이미지를 화면에 래스터화하는 것은 임의적인 형태에 그림자 효과를 그리는 것과는 완전히 다른 알고리즘적인 동작입니다. 그러므로 질문은 다음과 같습니다. 각기 다른 CSS 속성이 여러분의 페이지를 렌더링하는 비용에 어떤 영향을 줄까요?

제 목표는 CSS 속성들과 값들을 그들의 페인트 시간들에 따라 커다란 단위로 구분하는 것이었고 따라서 그것이 어떠한 형식의 CSS 속성들이 다른 것들보다 더 성능에 형향을 주는지에 대한 이해를 만들어 줄 수 있을 것입니다. 이를 위해 저는 CSS 페인트 시간을 수치적으로 시각화하는 것을 추가를 시도하기 위해 강력 접착 테이프와 풍선껌을 이용하여 다음과 같이 동작하는몇가지 자동화 작업들을 작성했습니다.

  • 각각이 단일한 DOM 엘리먼트와 그에 추가된 CSS 속성에 대한 몇가지 치환자를 가지고 있는 개별적인 HTML 페이지들의 스위트(suite)를 생성합니다.
  • 각 페이지에 대해 다음과 같은 자동화 스크립트를 실행합니다.
    • 크롬을 실행
    • 페이지를 로드
    • 페이지에 대한 Skia Picture를 생성
    • 시간값 획득을 위해 각 Skia Picture는 Skia 벤치마크를 통해 실행합니다.
  • 모든 시간값을 출력하고 숫자들에 대해 놀라워 합니다. (이 부분이 중요합니다.)
크롬의 소프트웨어 래스터라이저 패키지는 스키아(SKIA)로 불리며 단지 웹 페이지에 대한 래스터화만을 다루는 것이 아니라 HTML5 Canvas API가 필요로 하는 모든 것들(박스, 선, 비트맵 채우기, 그림자 효과, 흐림 효과, 크롬이 DOM을 픽셀들로 바꾸기 위해 호출하는 모든 것들)을 다룹니다. 페이지 렌더링의 디버깅을 돕기 위해 SKIA는 페이지의 페인트에 사용된 모든 명령들을 기록한 Skia Picture (*.SKP) 파일들을 저장할 수 있습니다.

역주: SKIA는 사실 WebKit 프로젝트에서 오랫동안 유지되어 온 렌더링 구조입니다. 크롬의 경우 WebKit에서 fork를 수행하면서 기존의 SKIA 모듈들이 Blink로 변경되었거나 되어가는 중입니다. 물론 기본적인 렌더링 메커니즘의 개념 자체가 크게 변경된 것은 아니기 때문에 구조 자체를 이해하는 부분에서는 큰 차이가 없으리라 생각합니다. Skia에 대해서는 기존 WebKit 프로젝트에 관련된 내용을 참조하시기 바랍니다.

이 설정을 이용하여 각 페이지가 CSS 속성들과 값의 유일한 순열을 포함하는 HTML 페이지들의 스위트(suite)를 생성합니다. 예를 들어 여기 다음과 같은 2개의 html 파일들이 있습니다.

<style>
#example1 {
    background: url(foo.png) top left / 50% 60%;
    padding: 20px;
    margin-top: 10px;
    margin-right: 20px;
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

그리고 또 다른 파일은 좀 더 복잡합니다.

<style>
#example1 {
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(circle closest-corner, white, black);
    padding: 20px;
    margin-top: 10px;
    margin-right: 20px;
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

아래는 이전 예제의 변형 예로써 다음과 같이 방사형-그레디언트(radial-gradient) 값만 변경하였습니다.

<style>
#example1
{
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(farthest-side, white, black);
    padding: 20px;
    margin-top: 10px;
    margin-right: 20px;
    text-align: center;
}
</style>
<div id="example1" style="padding: 20px; margin-top: 10px;margin-right: 20px; text-align: center;">WOAH</div>

각 페이지는 그 다음에 (페이지 새로고침 시 기존 상태에 의해 알 수 없게 편향된 타이밍을 보장하기 위해) 신선한 크롬의 인스턴스로 로딩되며 어떠한 Skia 명령이 페이지 페인트를 위해 사용되었는지를 평가할 수 있도록 Skia Picture (*.SKP)가가 얻어집니다. 한번 SKP 파일들이 각 HTML 파일에 대해 생성되고 나면 페이지의 렌더링에 걸린 평균 시간을 산출하는 Skia 벤치마크 어플리케이션을 통해 *.SKP 파일들을 밀어넣는 또다른 배치를 실행합니다. (Skia 벤치마크 어플리케이션은 Skia 소스 코드로부터 빌드됩니다.)

데이터의 평가

이를 통해 이제 우리는 CSS 속성들의 묶음(suite)이 페인트 시에 얼마나 많은 시간을 사용하는지를 기록하는 대략적인 기능 몇가지를 가지게 되었습니다. 혹은 차라리 CSS 속성들을 그들의 페인트 성능에 따라 스택 순위(Stack-ranking)를 매기기 시작할 수도 있습니다. 여기 크롬 27 베타 버전에서 얻어진 커다란 그래프는 이 처리 과정에서 얻어진 타이밍 데이터의 전체 세트를 보여줍니다. 모든 데이터는 크롬이 시간이 지나면 지날수록 빨라지는 것처럼 바뀔 수 있는 소재입니다.

테스트에서 모든 순열에 대한 시간값들

각 세로방향 막대는 CSS 속성들의 단일 조합을 가진 페이지의 페인트-시간을 표현합니다. (100배로 확대 시 이 그래프의 실제비율은 [0,1.56ms]입니다.) 많은 선이 예쁘게 그려져 있지만 이 형식에서 그것들은 어쨌던 쓸모가 없으며 유용한 추세를 발견하기 위한 몇가지 데이터 추출작업이 필요합니다.

첫번째로 다른 것들보다 렌더링에 평상적으로 더 비싼 비용이 드는 CSS 속성들에 대한 단서를 발견할 수 있습니다. 예를 들어 DO 엘리먼트에서 그림자효과를 출력하는 것은 지저분한 것들에 대한 스플라인(Spline) 및 다른 소트들을 이용하는 다단계(multi-pass) 동작을 발생하므로 이와는 대조적으로 투명도(opacity)가 렌더링하기에는 더 쉬울 것입니다.

 단 하나의 CSS 속성만을 가진 엘리먼트의 페인트에 걸리는 시간

두번째로 더 흥미로운 것은 CSS 속성의 조합은 그들 부분의 합보다 훨씬 더 많은 페이트 시간을 가질 수 있다는 것입니다. 우리는 A+B = C를 기대하지 2.2C를 기대하지는 않기 때문에 관찰자의 관점으로 볼 때 이는 약간 이상합니다. 다음과 같이 box-shadowborder-radius-stroke를 추가하는 경우가 그 예입니다.

테스트에서 모든 순열에 대한 시간값들

이에 대해 정말 흥미로운 점이 무엇이냐면 저것이 그냥 box-shadow 속성 자체라기 보다는 오히려 저것으로 인해 값 순열이 특정지어진다는 것입니다. 예를 들어, 아래는 box-shadow : 50%과 다양한 border-radius 값들로 그룹지어진 것들을 보여줍니다.

테스트에서 모든 순열에 대한 시간값들

잠시동안 데이터를 살펴보기를 시작하겠습니다. 다량의 다양하고 이상한 조합이 있으며, 제 테스트 스위트(suite)는 그들 전부를 거의 건드리지 않으며 흥미로운 결과들을 만들어내는 여전히 엄청난 양의 테스트와 조합이 있습니다.

페이지 렌더링-웨이트의 발견

페이지 상의 각 엘리먼트에 대한 렌더링 시간을 추적하는 능력으로 무기로 삼아 개발자들은 그들의 페이지-렌더링-웨이트과 사이트의 반응성에 얼마나 영향을 주는지를 평가할 수 있는 능력을 가지게 될 것이며 이를 시작할 수 있는 두가지 팁이 여기 있습니다.

  1. 어떤 CSS 속성들이 비용을 발생하는지를 이해하려면 크롬 개발자도구 내의 Continuous Paint mode를 사용합니다.
  2. 그라디언트(Gradient)과 그림자와 같은 더 비싼 비용으로 알려진 것들을 CSS 어디에서 사용하는지를 찾아 볼 성능 이슈를 잡아내고 싶다면 기존의 코드 리뷰 프로세스에 CSS 리뷰를 포함합니다. 내가 여기에 이게 필요한가? 스스로에게 물어봅시다.
  3. 의심스러울 때, 더 나은 성능의 편에 서는 것은 언제나 실수를 범하는 것입니다. 여러분의 사용자는 컬럼에서 패딩 너비(padding width)이 얼마인지 기억하지 못하지만 사이트를 방문했을 때 어떻게 느꼈는지는 기억할 것입니다.

불행하게도 하나로 구성된 것 같은 커스텀 타이밍 설정없이 크로스 플랫폼 페이지를 구축한 연속적인 통합을 포함하는 것을 어렵게 만드는 페이지-렌더링-웨이트를 발견하는 프로세스를 자동화하는 것은 현재 어렵습니다.

최종적인 의견

이 실험에 대한 가장 흥미로운 것들 중의 하나는 각 크롬 버전에서 변경이 지속될 시간값들입니다. (개인적으로느 더 빨라지기를 희망하고 있습니다.) 브라우저 소프트웨어는 변화무쌍한 표면적인 영역입니다. 무언가가 현재는 느리지만 내일은 빠를 수 있습니다. 여러분은 이 글에서 box-shadow: 1px 2px 3px 4px를 이미 border-radius:5를 가진 엘리먼트에 추가하는 것을 회피해야 한다는 것을 가지고 가게 되었습니다. 그러나 더 가치있게 가져가셔야 할 것은 CSS 속성들이 여러분의 페이지 페인트 시간에 직접적인 영향을 미친다는 것입니다.

어떠한 소프트웨어를 통해서도 디자인에 대한 결정을 하기 전에 어플리케이션 자체에서 타당성을 결정하기 위한 성능 대상들과 플랫폼들에 대한 디자인 상의 모든 선택들을 시험할 수는 없습니다.

참조 문서들

Comments

0