CSS 페인트 시간 및 페이지 렌더링 가중치

Colt McAnlis
Colt McAnlis

소개

브라우저의 작동 방식과 같은 내용을 꾸준히 알고 계시다면 최근 Chrome의 GPU 가속 렌더기/복합 작업에 대해 자세히 다룬 훌륭한 기사가 있었다는 것을 이미 알고 계실 것입니다. 먼저 Chrome의 가속 렌더링: 레이어 모델은 Chrome에서 레이어 개념을 사용하여 페이지를 그리는 방법을 소개합니다. 자세한 내용은 Chrome의 GPU 가속 컴포지팅을 참고하세요. 여기에서는 Chrome에서 GPU와 함께 이러한 레이어를 사용하여 페이지를 렌더링하는 방법을 설명합니다.

철학적 질문

3D 용도로 소프트웨어 래스터라이저를 작성하는 데 많은 시간을 보냈기 때문에 페이지를 그릴 때 일부 CSS 속성의 성능이 달라야 한다는 생각이 들었습니다. 예를 들어 작은 이미지를 화면에 래스터화하는 작업은 임의의 도형에 그림자를 그리는 것과는 완전히 다른 알고리즘 작업입니다. 따라서 다양한 CSS 속성은 페이지의 렌더링 무게에 어떤 영향을 미치나요?라는 질문이 제기되었습니다.

목표는 페인트 시간별로 대규모 CSS 속성/값을 분류하여 다른 속성보다 성능이 우수한 CSS 속성 유형을 파악하는 것이었습니다. 이를 위해 덕트테이프와 풍선껌으로 자동화를 작성하여 CSS 페인트 시간에 숫자 표시를 추가하려고 했습니다. 다음과 같이 작동했습니다.

  • 개별 HTML 페이지 모음을 생성합니다. 각 페이지에는 단일 DOM 요소와 연결된 CSS 속성의 일부 순열이 있습니다.
  • 각 페이지에 대해 다음을 실행하는 자동화 스크립트를 실행합니다.
    • Chrome 실행
    • 페이지 로드
    • 페이지의 Skia 그림을 생성합니다.
    • Skia 벤치마크를 통해 촬영한 각 Skia 사진을 실행하여 타이밍을 얻습니다.
  • 모든 타이밍을 버리고 수치에 놀라움을 금치 못합니다. (이 부분이 중요합니다.)

이 설정을 사용하면 각 페이지에 CSS 속성과 값의 고유한 순열이 포함된 HTML 페이지 모음이 생성됩니다. 예를 들어 다음은 두 개의 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>

그런 다음 각 페이지가 Chrome의 인스턴스에 로드되어(페이지 새로고침 시 오래된 상태로 인해 타이밍이 왜곡되지 않도록 하기 위함) Skia Picture(*.SKP)가 가져와 페이지를 페인팅하는 데 사용되는 Skia 명령어를 평가합니다. 각 HTML 파일에 대해 SKP 파일이 생성되면 다른 일괄 작업을 실행하여 Skia 소스 코드에서 빌드된 Skia 벤치마크 애플리케이션을 통해 *.SKP 파일을 푸시합니다. 그러면 해당 페이지를 렌더링하는 데 걸린 평균 시간이 덤프됩니다.

데이터 평가

이를 통해 이제 CSS 속성 모음이 페인트에 얼마나 걸리는지 차트를 대략적으로 생성할 수 있습니다. 또는 페인트 성능별로 CSS 속성을 스택 순위로 정렬할 수 있습니다. 다음은 Chrome 27 베타에서 가져온 큰 그래프입니다. 이 그래프는 이 프로세스의 모든 타이밍 데이터를 보여줍니다. Chrome이 점점 더 빨라짐에 따라 모든 데이터가 변경될 수 있습니다.

테스트의 모든 순열에 대한 시간

각 세로 막대는 CSS 속성의 단일 조합으로 페이지의 페인트 시간을 나타냅니다(100배 확대됨, 이 그래프의 실제 크기 값은 0.1.56ms). 멋진 선이 많이 있지만 이 형식에서는 다소 쓸모가 없습니다. 유용한 동향을 찾으려면 데이터 마이닝을 수행해야 합니다.

먼저 일부 CSS 속성은 다른 속성보다 렌더링하는 데 더 많은 비용이 든다는 증거를 찾습니다. 예를 들어 DOM 요소에 그림자를 그리려면 불투명도와 달리, 렌더링이 더 쉬워야 하는 불투명도와 달리, 스플라인과 다른 종류의 나쁜 것들을 사용하는 다중 패스 작업이 필요합니다.

CSS 속성이 1개인 요소를 페인트하는 데 걸린 시간

두 번째로, 더 흥미로운 점은 CSS 속성 조합의 페인트 시간이 부분의 합보다 더 클 수 있다는 점입니다. 관찰자의 관점에서 보면 약간 이상합니다. A+B = 2.2C가 아닌 C가 될 것으로 예상됩니다. 예를 들어 box-shadowborder-radius-stroke을 추가하는 경우 다음과 같습니다.

테스트의 모든 순열에 대한 타이밍

여기서 정말 흥미로운 점은 box-shadow 속성 자체가 아니라 특정 값 순열이라는 점입니다. 예를 들어 아래는 값 변형이 있는 box-shadow : 50%border-radius의 그룹화를 보여줍니다.

테스트의 모든 순열에 대한 타이밍

데이터를 보면 이 문제가 한동안 계속됩니다. 다양한 이상한 조합이 많이 있으며 테스트 모음은 거의 모든 조합을 다루지 않습니다. 흥미로운 결과를 얻을 수 있는 테스트와 조합은 아직 많이 있습니다.

페이지 렌더링 무게 찾기

페이지의 각 요소에 대한 렌더링 시간을 추적할 수 있는 기능을 사용하면 개발자는 page-render-weight와 사이트의 응답성에 미치는 영향에 대한 평가를 시작할 수 있습니다. 다음은 시작에 도움이 되는 몇 가지 도움말입니다.

  1. Chrome DevTools에서 Chrome의 연속 페인트 모드를 사용하여 비용이 많이 드는 CSS 속성을 파악합니다.
  2. 기존 코드 검토 프로세스에 CSS 검토를 통합하여 성능 문제를 포착합니다. CSS에서 그라데이션, 그림자와 같이 비용이 더 많이 드는 것으로 알려진 항목을 사용하는 위치를 찾습니다. '이 기능이 정말 필요한가요?'라고 자문해 보세요.
  3. 확실하지 않은 경우 항상 성능이 더 우수한 쪽을 선택하세요. 사용자는 열의 패딩 너비를 기억하지 못할 수도 있지만 사이트를 방문한 느낌은 기억할 것입니다.

맺음말

이 실험에서 가장 흥미로운 점은 타이밍이 Chrome 버전마다 계속 변경된다는 것입니다. 브라우저 소프트웨어는 끊임없이 변화하는 노출 영역입니다. 오늘 느린 속도도 내일은 빠를 수 있습니다. 이 도움말에서 벗어나면 이미 border-radius:5가 있는 요소에 box-shadow: 1px 2px 3px 4px를 넣지 않아도 됩니다. 하지만 더 중요한 점은 CSS 속성이 페이지 페인트 시간에 직접적인 영향을 미친다는 것입니다.

참조