"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > 성능을 저하시키는 두 줄의 CSS(fps ~ ps)

성능을 저하시키는 두 줄의 CSS(fps ~ ps)

2024-11-03에 게시됨
검색:752

최근에 Learn WCs를 출시했는데, 보신 분이라면 배경에서 색상이 지정된 원이 화면을 가로질러 대각선으로 움직이는 애니메이션을 보셨을 것입니다. 다음과 같습니다:

Chrome과 Safari에서는 잘 작동하지만 Firefox에서는 성능이 심각하게 저하되는 것을 발견했습니다.

성능이 너무 나빠서 Firefox에서 이 애니메이션을 곧바로 비활성화했습니다.

애니메이션은 어떻게 작동하나요?

애니메이션은 두 개의 중첩된 div를 사용하여 제작되었습니다. 외부 div는 사이트 본문 태그의 첫 번째 하위 항목입니다.

    

.ground-gradient 요소는 상위 컨테이너의 전체 너비와 높이에 걸쳐 있는 그라데이션을 생성하는 역할을 합니다. 다음과 같습니다:

The Two Lines of CSS That Tanked Performance (fps to ps)

외부 .Background-mask는 다음 두 가지를 담당합니다.

  1. 위치를 고정으로 설정하고 컨테이너가 뷰포트의 전체 크기를 채우도록 합니다.
  2. 그라디언트 위에 점선 마스크를 만듭니다.

이렇게 하면 점의 색상이 바로 아래에 있는 그라디언트의 색상과 동일해집니다.

The Two Lines of CSS That Tanked Performance (fps to ps)

위에서 설명한 모든 내용에 대한 CSS는 다음과 같습니다.

.background-mask {
    --mask-size: 24px;

    /* Position Styles */
    position: fixed;
    width: 100%;
    height: 100%;
    z-index: -1;

    /* Mask Styles */
    mask-image: radial-gradient(black 2px, transparent 2px);
    mask-size: var(--mask-size) var(--mask-size);
    mask-position: 0px 0px;
    animation: mask-move 3s infinite linear;
}

.background-gradient {
    background: var(--red);
    background-image: var(--gradient);
    width: 100%;
    height: 100%;
}

@keyframes mask-move {
    0% {
        mask-position: 0px 0px;
    }

    100% {
        mask-position: var(--mask-size) var(--mask-size);
    }
}

@media (prefers-reduced-motion: reduce) {
    .hero-background-mask {
        animation: none;
    }
}

CSS의 마스크에 대해 더 자세히 알아보고 싶다면 Ahmad Shadeed가 작성한 포괄적인 게시물을 추천해 드릴 수 있습니다.

성능 저하의 원인은 무엇입니까?

모든 CSS 속성이 동일하게 애니메이션되는 것은 아닙니다. 브라우저가 HTML을 페이지에 렌더링하는 방법에 대해 너무 자세히 설명하지 않고도(여기서 간략하게 설명했지만) 몇 가지 단계를 거치게 됩니다. 우리가 관심을 갖는 세 가지 단계는 다음과 같습니다.

  • 레이아웃 - 브라우저가 페이지 요소의 크기와 위치를 계산하는 경우
  • 페인트 ​​- 이미지, 색상, 그림자 등과 같은 페이지의 모든 시각적 측면을 그립니다.
  • 복합 - 올바른 순서로 요소를 서로 겹쳐서 배치

파이프라인의 순서는 다음과 같습니다.

레이아웃 → 페인트 → 합성

레이아웃 및 페인트 프로세스는 CPU를 많이 사용할 수 있으므로 CSS가 파이프라인의 단계를 트리거하는 횟수를 줄이는 것이 중요합니다*.* 브라우저는 특정 속성에 대한 성능을 최적화하여 어느 정도 도움을 줍니다. 렌더링 파이프라인의 전체 단계를 건너뛰고 다른 사람들은 하드웨어 가속을 활용하여 계산을 CPU에서 GPU로 이동할 수 있습니다.

번역 및 불투명도와 같은 특정 속성에 애니메이션을 적용하면 레이아웃 트리거를 방지하고 하드웨어 가속을 사용합니다.

안타깝게도 마스크 위치에 애니메이션을 적용할 때는 그렇지 않습니다. Chrome을 살펴보니 모든 프레임에서 배경 div의 페인트 수가 증가하는 것을 확인했습니다. 몇 초 후에 이미 1,000번 이상 페인트가 실행되었습니다.

The Two Lines of CSS That Tanked Performance (fps to ps)

이렇게 높은 페인트 개수에도 불구하고 Chrome의 애니메이션은 부드럽게 느껴집니다. 그러나 Firefox에서는 매우 버벅거리는 느낌이 듭니다. 짜증나게도 Firefox에서 페인트 수를 측정하는 방법을 찾을 수 없었기 때문에 Firefox의 성능 저하에 대한 제가 가정한 것은 순전히 추측일 뿐입니다.

제가 느낀 점은 작은 기기에서는 애니메이션이 괜찮지만 화면 크기가 커질수록 애니메이션이 나빠진다는 것입니다. 내 작업 이론은 Firefox가 각 24x24 마스크에 대한 레이아웃 트리거를 일괄 처리하지 않기 때문에 더 많은 24x24 마스크가 존재할 때 FPS가 중단된다는 것입니다. 다시 말하지만, 여기서는 제가 완전히 틀렸을 수도 있습니다.

이 문제를 어떻게 해결했나요?

mask-position 과 같이 잘못 최적화된 CSS 속성에 애니메이션을 적용하는 대신 번역과 같은 보다 성능이 뛰어난 속성에 의존해야 했습니다.

해결책은 마스크를 24픽셀씩 이동하는 것이 아니라 대신 번역 속성을 사용하여 전체 배경 요소를 이동하는 것이었습니다.

추상적인 관점에서 애니메이션은 다음과 같습니다.

다음은 CSS에서 두 줄로 변경된 내용입니다.

/* --mask-size = 24px */

@keyframes mask-move {
    0% {
        transform: translate(calc(var(--mask-size) * -1), calc(var(--mask-size) * -1));
    }

    100% {
        transform: translate(0px, 0px);
    }
}

브라우저는 더 이상 각 프레임에서 레이아웃을 트리거하는 마스크 위치에 애니메이션을 적용하지 않습니다. 배경이 각 프레임에서 이동하더라도 변환을 통해 레이아웃이나 페인트가 실행되지 않습니다. 페인트만 1분에 1,000개에서 두 번씩 줄어든 것을 볼 수 있습니다.

The Two Lines of CSS That Tanked Performance (fps to ps)

눈이 넓은 시청자라면 문제를 발견했을 것입니다. 기억하시면 배경의 높이와 너비가 뷰포트를 채웁니다. 배경을 왼쪽 및 위로 24px 이동하면 뷰포트에 빈 공간이 남습니다.

The Two Lines of CSS That Tanked Performance (fps to ps)

이 문제를 해결하려면 컨테이너의 너비와 높이에 마스크 크기를 추가하면 됩니다.

.background-mask {
    --mask-size: 24px;

    width: calc(100%   var(--mask-size));
    height: calc(100%   var(--mask-size));
}

Firefox에서 다시 살펴보겠습니다.

완벽한 해결책은 아닐 수도 있지만, 재미있는 연기 및 거울 CSS 트릭을 구현하는 것은 항상 약간 만족스럽습니다.

릴리스 선언문 이 기사는 https://dev.to/andrico1234/the-two-lines-of-css-that-tanked-performance-120fps-to-40fps-3lnj?1에서 복제됩니다. 침해가 있는 경우, Study_golang에 문의하세요. @163.com 삭제
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3