V8-isolate study
결국 독립적인 heap 메모리 할당, GC 등을 통하여 독립적인 실행 환경을 구성하도록 해준다.
https://github.com/nodejs/node/blob/main/src/node_worker.cc
위 파일에서 확인 시 Node.js의 worker_thread
또한 내부적으로 v8-isolate를 사용하여 구현된 것을 알 수 있는데,
그렇기에 동작이 매우 유사하다.
경량 스레드
경량 스레드는 (Light weight thread) 는 일반적인 스레드와 달리 운영체제 커널에서 관리되지 않고 유저 레벨에서 관리되는 스레드이다. 효율적인 멀티스레딩 환경을 제공하고, 커널의 간섭 없이 애플리케이션 수준에서 이를 스케쥴링 및 컨텍스트 스위칭을 할 수 있도록 한다.
경량 스레드의 수동 구현
경량 스레드를 직접 구현하기 위해서는 크게 스케쥴러와 컨텍스트 스위칭 기능을 구현할 수 있어야 한다.
스케쥴러: 현재 실행 중인 스레드를 다른 스레드로 교체하고, 일정한 규칙에 따라 스레드를 실행하는 역할을 한다.
- 스케쥴러는 크게 RR혹은 FCFS, SJF 와 같은 전통적인 스케쥴링 알고리즘에 의해 동작할 수 있다.
- 스케쥴링 알고리즘의 이해
컨텍스트 스위칭: 경량 스레드 간의 문맥 전환을 하려면 CPU 레지스터, 스택 포인터 등을 저장하고 복원하는 과정이 필요하다. 이는 주로 어셈블리어 수준에서 구현되는데, CPU 상태를 저장하고 다른 스레드로 전환하는 과정이 필요하다.
실제 적용 시 주의점
- 비동기 I/O: 비동기 처리를 통해 전체 성능 저하를 막기
- 커널 스레드와 혼합: 하이브리드 접근 방식에 해당되는데, 커널 스레드를 통해 I/O 블로킹 문제를 해결하면서 경량 스레드의 성능 장점을 살릴 수 있다.
- 스케쥴러 최적화: 유저 레벨 스케쥴러의 효율성이 좋을 수록 성능에 직접적인 영향을 미치므로, 스레드의 우선순위, 컨텍스트 스위칭 빈도 등을 각 상황에 맞게 최적화할 수 있어야한다.
특징
- 유저 레벨에서의 관리
- 커널 모드의 개입 없이 유저 모드에서 동작한다. 이를 통해 컨텍스트 스위칭 비용을 줄이고 성능을 개선한다.
- 운영체제가 이를 인식하지 못하므로, 여러 경량 스레드가 하나의 커널 스레드에서 실행 가능하다.
- 빠른 스케쥴링
- 시스템 콜과 같은 운영체제 자원의 추가 소모가 없기 때문에 더 적은 오버헤드를 가질 수 있다.
- 운영체제와 독립적인 동작
- 커널 스레드는 운영체제에 의해 스케쥴링되지만, 경량 스레드는 유저 레벨에서 스케쥴링을 담당하므로 운영체제가 이를 알지 못함.
- CPU 코어 수 등에 종속되지 않고 많은 경량 스레드를 운용할 수 있다.
- 블로킹 문제
- 유저 레벨에서 관리되므로, 하나의 경량 스레드가 블로킹되면 같은 커널 스레드에서 동작하는 다른 경량 스레드가 영향을 받을 수 있다. 이를 위해 비동기 I/O 혹은 다중화 기법 등을 적용해야한다.