React 스케줄 러 원리 분석

5339 단어
Fiber
React 16 의 새 버 전에 서 Fiber 를 사용 하여 React 의 핵심 알고리즘 을 재 구현 하여 킬 링 카드 증분 업데이트 기능 을 가 져 왔 습 니 다.전체 업데이트 작업 을 작은 작업 으로 나 눌 수 있 고 이 작업 의 수행 을 제어 할 수 있 습 니 다.이러한 기능 은 주로 두 핵심 기술 을 통 해 이 루어 진다.
• 새로운 데이터 구조 fiber
스케줄 러
이 글 은 주로 스케줄 러 의 원 리 를 해석 하고 있다.
스케줄 러 안내
왜 스케줄 이 필요 합 니까?
JS 와 렌 더 링 엔진 은 상호 배척 관계 라 는 것 을 모두 가 알 고 있다.JS 가 코드 를 실행 하고 있 으 면 렌 더 링 엔진 작업 이 중 단 됩 니 다.만약 우리 가 매우 복잡 한 복합 구성 요 소 를 다시 렌 더 링 해 야 한다 면, 호출 스 택 은 매우 길 수 있 습 니 다.
스 택 을 너무 오래 호출 한 데다 가 중간 에 복잡 한 조작 을 하면 렌 더 링 엔진 이 장시간 차단 되 어 좋 지 않 은 사용자 체험 을 가 져 올 수 있 습 니 다. 브 라 우 저 는 카드, 가사 상황 을 나 타 낼 수 있 습 니 다. 스케줄 링 은 이 문 제 를 해결 하 는 것 입 니 다.
React 는 퀘 스 트 의 우선 순위 에 따라 각자 의 expirationTime 을 분배 합 니 다. 기한 이 지나 기 전에 더 높 은 우선 순위 의 퀘 스 트 를 처리 하고 높 은 우선 순위 의 퀘 스 트 는 낮은 우선 순위 의 퀘 스 트 를 중단 할 수 있 습 니 다 (따라서 일부 생명주기 함수 가 여러 번 실 행 될 수 있 습 니 다). 따라서 현재 사용자 체험 에 영향 을 주지 않 는 상황 에서 단계별 계산 업데이트시간 분할.
React 스케줄 링 의 실현
React 는 주로 두 부분 에서 이 루어 집 니 다.
1. 퀘 스 트 를 계산 하 는 expriationTime
2. request IdleCallback 을 실현 하 는 poly fill 버 전
expriationTime
expriationTime 이 시간 은 서로 다른 작업 간 의 우선 순위 와 작업 을 계산 하 는 timeout (만 료 여부) 를 비교 하 는 데 사 용 됩 니 다.
계산 공식: expriationTime = 현재 시간 + 상수 (작업 우선 순위 에 따라 변경)
현재 시간 은 performance. now () 를 말 합 니 다. 이 API 는 밀리초 단위 로 정확 한 시간 스탬프 를 되 돌려 줍 니 다. (물론 높 은 정밀도 도 아 닙 니 다) 또한 브 라 우 저 는 모든 것 이 performance API 를 호 환 하 는 것 이 아 닙 니 다. Date. now () 를 사용 하면 정밀도 가 더 떨 어 집 니 다. 하지만 편 의 를 위해 현재 시간 을 performance. now () 로 통일 합 니 다.。
상수 란 서로 다른 우선 순위 에 따라 얻 은 수 치 를 말한다. React 내부 에는 현재 모두 다섯 가지 우선 순위 가 있 고 수치 가 작 을 수록 우선 순위 가 높다. 각각 다음 과 같다.
var ImmediatePriority = 1;
var UserBlockingPriority = 2;
var NormalPriority = 3;
var LowPriority = 4;
var IdlePriority = 5;

그들 각자 의 대응 수 치 는 모두 다 르 고 구체 적 인 내용 은 다음 과 같다.
var maxSigned31BitInt = 1073741823;

// Times out immediately
var IMMEDIATE_PRIORITY_TIMEOUT = -1;
// Eventually times out
var USER_BLOCKING_PRIORITY = 250;
var NORMAL_PRIORITY_TIMEOUT = 5000;
var LOW_PRIORITY_TIMEOUT = 10000;
// Never times out
var
IDLE_PRIORITY = maxSigned31BitInt;

즉, 현재 시간 이 5000 이 고 각각 두 개의 우선 순위 가 다른 임 무 를 수행 해 야 한다 고 가정 합 니 다. 전 자 는 ImmediatePriority 에 속 하고 후 자 는 UserBlockingPriority 에 속 합 니 다. 그러면 두 임 무 는 각각 4999 와 5250 (값 이 작 을 수록 우선 수행 해 야 합 니 다) 입 니 다.... 이 시간 을 통 해 크기 보다 누구의 우선 순위 가 높 은 지 알 수 있 고, 현재 시간 을 빼 서 작업 의 timeout 을 얻 을 수 있 습 니 다.
requestIdleCallback
requestIdleCallback 은 웹 api 인터페이스 입 니 다. 브 라 우 저의 여가 시간 에 함 수 를 순서대로 호출 합 니 다. 이 는 개발 자 들 이 메 인 이벤트 순환 에서 배경 이나 낮은 우선 순위 의 작업 을 수행 할 수 있 고 애니메이션 과 사용자 의 상호작용 처럼 지연 되 고 민감 한 이벤트 에 영향 을 주지 않 습 니 다. 함 수 는 일반적으로 먼저 호출 된 순서대로 실 행 됩 니 다. 그러나 리 셋 함수 가 지정 되면시간 초과 timeout 을 실행 하면 시간 초과 전에 함 수 를 실행 하기 위해 순 서 를 흐 트 러 뜨 릴 수 있 습 니 다. timeout 값 이 양수 로 지정 되 었 을 때 브 라 우 저 로 콜백 을 호출 하 는 마지막 기한 입 니 다. 단 위 는 밀리초 입 니 다. 지정 한 시간 이 지나 도 리 셋 이 실행 되 지 않 으 면 리 셋 은 다음 여가 시간 에 강제 적 으로 실 행 됩 니 다. 성능 에 마이너스 가 될 수 있 지만.직접적인 영향.
그러나 request IdleCallback 은 치 명 적 인 결함 이 있 습 니 다. 1 초 에 20 번 만 호출 할 수 있 습 니 다. 이것 은 기 존의 상황 을 만족 시 킬 수 없 기 때문에 React 팀 은 스스로 이 함 수 를 실현 합 니 다.
requestIdleCallback 요점 실현
request IdleCallback 을 실현 하 는 것 은 브 라 우 저 가 비어 있 을 때 여러 번 렌 더 링 을 한 후에 리 셋 방법 을 호출 하 는 것 입 니 다.
request Animation Frame 을 여러 번 실행 할 수 있 습 니 다. 브 라 우 저의 각 프레임 을 다시 그리 기 전에 들 어 오 는 함 수 를 실행 할 수 있 기 때문에 정확 합 니 다. 주류 브 라 우 저 에 서 는 브 라 우 저 새로 고침 빈도 가 60 헤르츠 이 고 1 초 에 60 번 이 며 한 번 에 16 밀리초 정도 걸 립 니 다.
브 라 우 저 가 현재 비어 있 는 지 여 부 를 어떻게 판단 합 니까? 한 프레임 에서 브 라 우 저 는 사용자 의 대화 이벤트 에 응답 하고 JS 를 실행 하 며 렌 더 링 을 하 는 일련의 계산 그리 기 를 할 수 있 습 니 다. 만약 상기 작업 이 16ms 를 초과 하면 이 프레임 렌 더 링 이 완성 되 지 않 고 프레임 이 떨 어 지 는 상황 이 발생 하여 페이지 에 뚜렷 한 카드 가 생 겨 사용자 에 게 영향 을 줄 수 있 습 니 다.체험; 만약 에 상기 조작 이 16ms 를 소모 하지 않 았 다 면 우 리 는 현재 여가 시간 이 있어 서 우 리 는 임 무 를 수행 할 수 있다 고 생각 합 니 다.
계산 방법 은 참고 문헌 을 참조한다.
쉽게 말 하면 현재 시간 이 5000 이 고 브 라 우 저가 60 프레임 을 지원 한다 고 가정 하면 1 프레임 이 16 밀리초 에 가깝다 면 다음 프레임 의 시간 은 5016 이다.
다음 프레임 의 시간 을 얻 은 후에 우 리 는 현재 시간 이 다음 프레임 보다 적 는 지 비교 하면 된다. 그러면 임 무 를 수행 할 시간 이 있 는 지 를 분명히 알 수 있다.
마지막 으로, 우 리 는 렌 더 링 을 한 후에 야 임 무 를 수행 해 야 합 니 다. 이벤트 loop 에 따라 매크로 임 무 를 수행 하고, 하나의 대기 열 에 있 는 마이크로 임 무 를 수행 하 는 것 이 가장 적합 하기 때 문 입 니 다. 매크로 임 무 를 가장 빨리 완성 할 수 있 도록 Message Channel 에 두 고 이 임 무 를 수행 합 니 다.
스케줄 링 프로 세 스
  • 우선 모든 퀘 스 트 는 각자 의 우선 순위 가 있 습 니 다. 현재 시간 에 우선 순위 에 대응 하 는 상수 를 더 하면 expriationTime 을 계산 할 수 있 습 니 다. 높 은 우선 순위 의 퀘 스 트 는 낮은 우선 순위 퀘 스 트
  • 를 중단 합 니 다.
  • 스케줄 링 전에 현재 작업 이 만 료 되 었 는 지 판단 합 니 다. 만 료 되면 스케줄 링 할 필요 가 없습니다. port. postmessage (undefined) 를 직접 호출 하면 렌 더 링 후 바로 만 료 작업 을 수행 할 수 있 습 니 다
  • 작업 이 만 료 되 지 않 았 다 면 requestAnimationFrame 을 통 해 타 이 머 를 시작 하고 다시 그리 기 전에 리 셋 방법
  • 을 호출 합 니 다.
  • 리 셋 방법 에서 우 리 는 먼저 각 프레임 의 시간 과 다음 프레임 의 시간 을 계산 한 다음 에 port. postmessage (undefined)
  • 를 실행 해 야 한다.
  • channel. port1. onmessage 는 렌 더 링 후 호출 됩 니 다. 이 과정 에서 우 리 는 먼저 현재 시간 이 다음 프레임 보다 적 는 지 판단 해 야 합 니 다. 작 으 면 우리 가 아직 작업 을 수행 할 시간 이 있다 는 것 을 의미 합 니 다. 크 면 현재 프레임 에 시간 이 없다 는 것 을 의미 합 니 다. 이 럴 때 우 리 는 작업 이 만 료 되 었 는 지, 만 료 되 었 는 지 판단 해 야 합 니 다.이 임 무 를 수행 해 야 합 니 다. 기한 이 지나 지 않 았 다 면 현재 프레임 에 시간 이 없 었 습 니 다. 이 임 무 를 다음 프레임 에 던 져 서 수행 할 수 있 는 지 없 는 지 볼 수 밖 에 없 었 습 니 다
  • 본 고 는 전체적으로 yck, juejin. im / post / 5cef 53 을 참고 한다.
    원래 의 기초 위 에 자신의 이 해 를 넣 었 다.

    좋은 웹페이지 즐겨찾기