Переход между JS и C++ требует сериализации/десериализации данных и контекстного переключения:
const addon = require('./native-addon');
// Каждый такой вызов - переход между V8 и нативным кодом
const result = addon.compute(42);
Преобразование типов между JS и C++:
JavaScript тип | C++ тип | Накладные расходы |
---|---|---|
Number | double/int32_t | Минимальные |
String | char*/v8::String | Копирование |
Object | v8::Object | Глубокий анализ |
Buffer | char* | Копирование |
Хотя N-API стабильнее Native Abstractions, он добавляет уровень абстракции:
napi_status napi_get_value_double(napi_env env, napi_value value, double* result);
Каждый вызов N-API функции:
Синхронные вызовы нативного кода блокируют основной поток:
// Этот вызов остановит весь Event Loop
const result = addon.syncCompute();
Нативный метод, который просто возвращает число:
Napi::Number Add(const Napi::CallbackInfo& info) {
double a = info[0].As<Napi::Number>().DoubleValue();
double b = info[1].As<Napi::Number>().DoubleValue();
return Napi::Number::New(info.Env(), a + b);
}
Вызов из JS:
const sum = addon.add(2, 3); // В 100-1000 раз медленнее чисто JS
Пакетные операции:
Асинхронные вызовы:
Буферы вместо объектов:
Кэширование часто используемых значений:
static napi_value cachedValue;
if (!cachedValue) {
napi_create_string_utf8(env, "cached", NAPI_AUTO_LENGTH, &cachedValue);
}
Основные причины замедления:
Критические моменты:
Оптимизации:
Для максимальной производительности минимизируйте переходы между JS и нативным кодом и оптимизируйте передачу данных.