V8 Fast API에 대하여 2

V8 Fast API 사용

이전 Post에 이어 본 페이지에서는 V8 Fast API 를 코드 상에서 어떻게 사용하는 확인하고 어떻게 기존 API와 다른지 확인해본다.

1. Add functions for Fast API

Slow API의 경우 FunctionCallbackInfo를 인자로 받는것에 비해 Fast API는 입력값 자체를 파라미터로 받는다.

1
2
3
4
5
6
7
8
9
10
static double FastDivide(const int32_t a,
const int32_t b,
v8::FastApiCallbackOptions& options) {
if (b == 0) {
options.fallback = true;
return 0;
} else {
return a / b;
}
}

2. Fallback Slow API

Fallback API는 사용자 지정 오류를 발생시키거나 자바스크립트 코드를 실행해야 할 때와 같이 느린 경로로 전환하는 것이 바람직한 경우에 대비해 폴백을 지원한다. Fallback 메커니즘은 Fast API 함수 선언의 C++ 구현에서 활성화 및 변경할 수 있는데, V8에서 FastApiCallbackOptions 을 true로 전달한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static void SlowDivide(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_GE(args.Length(), 2);
CHECK(args[0]->IsInt32());
CHECK(args[1]->IsInt32());
auto a = args[0].As<v8::Int32>();
auto b = args[1].As<v8::Int32>();

if (b->Value() == 0) {
return node::THROW_ERR_INVALID_STATE(env, "Error");
}

double result = a->Value() / b->Value();
args.GetReturnValue().Set(v8::Number::New(env->isolate(), result));
}

이렇게 지정된 API는 아래와 같이 JavaScript를 실행했을때 각각 Fast, Slow Path를 따라 실행하게 된다.

1
2
divide(2, 2); // calls fast path
divide(2, 0); // calls fallback (slow path)

기존에, SetMethodSetMethodNoSideEffect 를 통해 객체에 binding API를 등록했던것과 다르게 SetFastMethod 를 이용하여 Fast API를 등록한다. 4번째 인자로 Fallback API를 전달한다.

1
2
3
4
5
6
7
8
9
10
CFunction fast_divide_(CFunction::Make(FastDivide));

static void Initialize(Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
// SetMethodNoSideEffect(context, target, "divide", SlowDivide);
SetFastMethod(context, target, "divide", SlowDivide, &fast_divide_);
}

3. Snapshot을 위한 등록

어떤 API를 Snapshot으로 만들어야할지 직접 코드상에서 등록해야한다.

1
2
3
4
5
6
// Snapshot
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
registry->Register(SlowDivide);
registry->Register(FastDivide);
registry->Register(fast_divide_.GetTypeInfo());
}

Reference

Share