QuickJS

Juppi·2024년 9월 24일
4

Javasript Engine

목록 보기
2/2

QuickJS는 작고 embeddable한 경량 자바스크립트 엔진으로, asynchronous generators, proxy, BigInt를 포함한 ES2020 사양을 지원한다. 가벼운 환경에서 빠르게 로딩하고 적은 리소스로 간단한 작업을 처리하는데 최적화된 엔진이다.

✨ Features

Small, easily embeddable, lightweight

외부 라이브러리가 포함되어있지 않은 약 210KiB의 C 파일로 이루어졌으며, C API를 통해 다른 어플리케이션과 쉽게 통합할 수 있다.

Fast interpreter with very low startup time

런타임 인스턴스의 전체 수명 주기가 0.3 ms 이내에 완료됨.

No JIT compile

QuickJs는 JIT 컴파일러가 없는 인터프리터 기반의 엔진이다.
JIT가 없기 때문에 V8 같은 엔진보다는 성능 면에서 약간 느릴 수 있지만, 실행환경에서 빠르게 로딩되고 메모리 사용량이 매우 적다.

Interpreter vs JIT Compiler

  • Interpreter는 자바스크립트 코드를 한 줄 한 줄 읽으면서 실행한다. 해당 방식은 빠르게 시작할 수 있지만, 반복되는 코드나 복잡한 로직에서는 비효율적이다. 예를 들어, 같은 코드를 여러 번 실행할 때는 매번 그 코드를 해석해야하기 때문에 컴파일러 방식의 동작에 비해 느릴 수 있다.
  • JIT 컴파일 방식은 자바스크립트 코드를 실행하기 전에 미리 컴파일해서 최적화된 머신 코드로 변환한 후 실행한다. 실행 전에 최적화 작업이 들어가서, 컴파일을 위한 추가 시간이 필요하기 때문에 즉각적인 실행속도는 느릴 수 있으나, 반복적인 코드나 복잡한 로직에서 성능을 크게 향상시킬 수 있다.

가상 머신과 바이트 코드

QuickJS는 자바스크립트 코드를 바이트코드로 컴파일하여 실행한다. 이 바이트코드는 메모리 내에서 실행되며, 별도로 저장하여 재사용할 수도 있다.

인터프리터와 가상머신/바이트 코드

인터프리터 방식은 소스 코드를 한 줄씩 읽고 해석하여 실행하는 것을 말한다. 자바스크립트 엔진에서 이 인터프리터가 가상 머신과 바이트코드를 사용하면, 실행 방식이 더 효율적으로 변할 수 있다.

1.	바이트코드 생성: 자바스크립트 소스 코드를 직접 해석하여 실행하는 대신, 우선 자바스크립트 소스 코드를 바이트코드로 변환한다. 바이트코드는 실행에 필요한 중간 단계의 코드이며, 이 변환은 엔진 내에서 일어난다.
2.	가상 머신에서 실행: 변환된 바이트코드를 실제로 실행하는 곳이 바로 **가상 머신(VM)**이다 이 가상 머신은 바이트코드를 해석하여 실행하며, 물리적 CPU에서 직접적으로 실행하는 것보다는 효율적이다. 바이트코드가 고수준의 자바스크립트 코드보다 더 최적화되어 있기 때문이다.

QuickJS는 인터프리터 기반의 자바스크립트 엔진이지만, 가상 머신과 바이트코드를 사용한다. 즉, 자바스크립트 소스 코드를 먼저 바이트코드로 변환하고, 그 바이트코드를 QuickJS의 가상 머신에서 실행한다. 이를 통해 자바스크립트 코드를 직접 해석하며 실행하는 것보다 더 효율적인 실행 환경을 제공한다.

인터프러터방식에서 가상 머신과 바이트코드를 사용하는 이유

1.	최적화된 코드 실행: 자바스크립트 코드를 한 줄씩 해석하여 실행하는 대신, 먼저 바이트코드로 변환함으로써 더 최적화된 형태로 실행할 수 있다. 이렇게 하면 인터프리터가 매번 자바스크립트 구문을 해석할 필요가 없으므로 실행 속도가 빨라진다.
2.	이식성: 바이트코드는 하드웨어에 종속되지 않고, 가상 머신을 통해 여러 환경에서 실행할 수 있다. 이를 통해 다양한 플랫폼에서 동일한 자바스크립트 코드를 실행할 수 있게 된다.
3.	메모리 효율성: 바이트코드는 소스 코드에 비해 메모리 사용량이 적으며, 메모리 제약이 있는 환경에서 효율적으로 실행할 수 있다. QuickJS 같은 엔진은 이러한 효율성 덕분에 임베디드 시스템에서 사용하기 적합하다.

ARC (Automatic Reference Counting)

참조 카운팅을 사용하여 객체의 메모리를 관리하고, 참조 사이클을 제거하는 방식으로 메모리 누수를 방지하여 결정론적인 메모리 관리가 가능

결정론적인 메모리 관리란, 메모리 할당과 해제가 언제 발생하는지 명확하게 예측할 수 있는 메모리 관리 방식을 뜻함. 즉, 어떤 객체가 메모리에서 해제될 시점을 개발자가 정확하게 알 수 있음.

참조 카운팅이 일으키는 순환 참조 문제를 구체적으로 어떻게 해결했는지 ?

주기 제거 기능이 있는 참조 카운팅을 사용하여 자동으로 객체를 자유롭게 결정한다. 이렇게하면 메모리 사용이 줄어들고 JavaScript 엔진의 결정적인 동작이 보장되게 함

Mathmetical extentions

BigDecimal, BigFloat, operator overloading, bigint mode 지원

reference

https://gist.github.com/guest271314/bd292fc33e1b30dede0643a283fadc6a
https://cwn.kr/article/179564348810714

1개의 댓글

comment-user-thumbnail
2024년 9월 24일

천재시네요

답글 달기