V8 Fast API에 대하여 1

V8 Fast API

V8 JavaScript 엔진은 JIT 컴파일을 수행할 수 있는 JavaScript 엔진이다. 그런데, 이런 JIT에서 얻을 수 있는 최적화 장점이 C++ Binding에는 적용되기 어렵다. 그래서 매번 C++ 과 JS를 오가며 변환, 설정 과정이 수반되는 Call을 불러야했다. 그로인한 성능의 저하가 있었다.

JIT(Just-In-Time) 컴파일은 프로그램을 실행하는 동안 실제로 필요한 코드 부분만 컴파일하는 기술이다. 일반적으로 JavaScript 코드는 한 줄씩 인터프리터에 의해 해석되지만, JIT 컴파일러는 자주 사용되는 함수나 루프 같은 핵심 코드를 미리 컴파일하고 최적화하여 실행 속도를 높인다.

Fast API 는 C++ 바인딩 코드에 대해서도 IR 코드로 전환될 수 있도록 지원하는 기능이다. 향후 C++ 코드를 부르지 않기 때문에 빠를 수 밖에 없다. 그러나 모든 V8 모든 C++ API 에 대해서 지원하는 것은 아니고 사용에 따른 제약이 존재한다.

제약사항

Fast API가 도입되었던 시기의 제약사항은 다음과 같았다. 현재에는 어떻게 달라졌는지 확인해볼것이지만 아마 핵심적인 컨셉은 변경되지 않을 것이다.

1. JS Heap에 할당되서는 안된다

JS Heap은 가비지 컬렉션에 의해 관리되는데 이는 성능에 부담을 일으킬수 있는 작업이고 메모리 할당 또한 마찬가지다. 성능을 향상시키기 위한 제약조건으로 보여진다. 실 예로 따지면 v8::Array::Get() or v8::Number::New() 와 같은 작업을 할 수 없다.

2. JS 코드를 다시 호출해서는 안된다

C++ 코드가 다시 JS 코드를 호출하면 안된다. JIT 컴파일러가 생성한 최적화된 코드 내에서 다시 JavaScript 코드를 호출하거나 실행하면 안 된다는 원칙을 나타낸다. 예를 들어, JIT 컴파일러가 일부 코드를 최적화하고 기계 코드를 생성하였는데, 그 중에 JavaScript 함수를 호출하는 부분이 있다고 가정해보자. 이렇게 되면 기계 코드 내에서 JavaScript 엔진의 실행 흐름을 따라가야 하므로 최적화된 코드의 성능 향상 효과가 상쇄될 수 있다. 따라서 Fast API 코드 내에서 JavaScript 코드 호출을 허용하지 않고, 순수한 기계 코드로만 구성되도록 보장한다. 이렇게 함으로써 최적화된 코드의 성능 개선 효과를 유지하면서 예측 가능하고 안정적인 실행을 보장한다.

3. 에러를 Throw 하는 것도 허용되지 않는다

마찬가지로 Error 처리하는데 속도문제가 있을것으로 생각된다. Fast API를 등록할때, fallback 도 등록하게 되는데, Error Throwing이 필요한 경우 fallback api (Slow API) 에서 작업하면 된다.

4. 모든 Input type과 return type 지원하는것이 아니다

현재 지원하는 코드에 대해서는 아래의 코드에서 확인할 수 있다.

v8-fast-api-calls.hlink
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
* Currently supported return types:
* - void
* - bool
* - int32_t
* - uint32_t
* - float32_t
* - float64_t
* Currently supported argument types:
* - pointer to an embedder type
* - JavaScript array of primitive types
* - bool
* - int32_t
* - uint32_t
* - int64_t
* - uint64_t
* - float32_t
* - float64_t
Share