이 문서는 Node.js의 타이머에 대한 관련 정보를 공유합니다. 도움이 필요한 친구들이 참조할 수 있습니다.
Node.js에서 타이머 구현
이전 블로그 게시물에서 언급했듯이 Node의 타이머는 새 스레드를 열어서 구현하는 것이 아니라, 이벤트 루프. 다음은 여러 JavaScript 타이머 예제와 Node 관련 소스 코드를 사용하여 Node.js에서 타이머 기능이 어떻게 구현되는지 분석합니다.
JavaScript의 타이머 함수 특성
Node든 브라우저든 setTimeout과 setInterval이라는 두 가지 타이머 함수가 있으며 작동 특성은 기본입니다. 동일하므로 아래 분석 예시로는 Node만 사용합니다.
우리는 JavaScript의 타이머가 컴퓨터의 기본 예약된 인터럽트와 다르지 않다는 것을 알고 있습니다. 인터럽트가 도착하면 현재 실행 중인 코드가 중단되고 예약된 인터럽트 처리 기능으로 전송됩니다. JavaScript 타이머가 만료되면 현재 실행 스레드에 실행 중인 코드가 없으면 해당 콜백 함수가 실행됩니다. 현재 실행 중인 코드가 있으면 JavaScript 엔진은 콜백을 실행하기 위해 현재 코드를 중단하지도 않습니다. start 새 스레드가 콜백을 실행하지만 현재 코드가 실행된 후에 처리됩니다.
console.time('A') setTimeout(function () { console.timeEnd('A'); }, 100); var i = 0; for (; i < 100000; i++) { }
위 코드를 실행해보면 최종 출력 시간이 100ms 정도가 아니고 몇 초 정도 되는 것을 알 수 있습니다. 이는 예약된 콜백 함수가 실제로 루프가 완료되기 전에 실행되지 않고 루프가 끝날 때까지 연기됨을 보여줍니다. 실제로 JavaScript 코드 실행 중에는 모든 이벤트를 처리할 수 없으며, 현재 코드가 완료될 때까지 새 이벤트를 처리할 수 없습니다. 이것이 시간이 많이 걸리는 JavaScript 코드를 실행할 때 브라우저가 응답하지 않는 이유입니다. 이러한 상황을 해결하기 위해 Yielding Processes 기술을 사용하여 시간이 많이 걸리는 코드를 작은 청크(청크)로 나눌 수 있습니다. 각 청크가 처리된 후 setTimeout이 한 번 실행되고 다음 청크가 처리되도록 합의할 수 있습니다. 이 기간 동안 유휴 시간 동안 브라우저/노드는 대기 중인 이벤트를 처리할 수 있습니다.
보충 정보
제22장 JavaScript 고급 프로그래밍의 고급 기술, 제3판에서 고급 타이머 및 항복 프로세스에 대해 더 자세히 설명합니다.
Node에서 타이머 구현
libuv의 uv_loop_t 유형 초기화
이전 블로그 게시물에서 Node가 libuv의 uv_run 함수를 호출하여 default_loop_ptr을 시작한다고 언급했습니다. 이벤트용 스케줄링에서 default_loop_ptr은 uv_loop_t 유형의 default_loop_struct 변수를 가리킵니다. Node가 시작되면 uv_loop_init(&default_loop_struct)를 호출하여 초기화합니다. uv_loop_init 함수의 발췌는 다음과 같습니다:
int uv_loop_init(uv_loop_t* loop) { ... loop->time = 0; uv_update_time(loop); ... }
시간 필드를 볼 수 있습니다. of loop에는 먼저 0 값이 할당된 다음 uv_update_time 함수를 호출하여 최신 계산 시간을 loop.time에 할당합니다.
초기화가 완료된 후 default_loop_struct.time에는 초기값이 있으며, 시간 관련 연산은 이 값과 비교하여 해당 콜백 함수를 호출할지 여부를 결정합니다.
libuv의 이벤트 스케줄링 핵심
앞서 언급했듯이 uv_run 함수는 이벤트 루프를 구현하는 libuv 라이브러리의 핵심 부분입니다.
다음은 타이머와 관련된 위 로직에 대한 간략한 설명입니다.
"현재"를 표시하는 현재 루프의 시간 필드를 업데이트합니다. 현재 루프 개념에서
등록된 타이머를 확인하고, 특정 타이머가 현재 시간보다 늦으면 타이머가 만료되었음을 나타내므로 해당 콜백 함수가 실행됩니다.
O 폴링(즉, 스레드를 차단하고 I/O 이벤트가 발생할 때까지 대기) 다음과 같은 경우 타이머가 만료될 때 I/O가 완료되지 않으면 대기를 중지하고 다음 타이머의 콜백을 실행합니다.
(사실 (4.) 여기서는 한 단계 작업이 아니라 더 복잡합니다. 이 설명은 다른 세부 사항을 포함하지 않고 타이머 구현에만 중점을 두기 위한 것입니다.)
노드는 uv_run을 계속 호출합니다. 루프가 더 이상 살아 있지 않습니다.
노드 시작 및 전역 초기화
이전 기사에서는 Node가 시작될 때 실행 환경 LoadEnvironment(env)를 로드한다고 언급했습니다. 이 함수에서 매우 중요한 단계는 src/node.js를 로드하고 이를 실행하는 것입니다. 모듈과 전역 및 프로세스를 초기화합니다. 물론 setTimeout과 같은 함수도 src/node.js에 의해 전역 개체에 바인딩됩니다.
위 내용은 이 글의 전체 내용입니다. 모두 마음에 드셨으면 좋겠습니다.
Node.js의 타이머와 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!