Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

371
Visualizações
How to generate JsObject in Node.js c++ addon as fast as in pure js?

I am new as a Node.js cpp-addon developer, I need to return a very big Object from cpp(Node.js cpp-addon) to Javascript logic, but I found that it is very slow to generate JsObject in C++ addon rather than pure js. Here is my code and running result:

cpp-addon case:

var addon = require('bindings')('addon.node')

console.time('perf');
console.log('This should be result:', addon.getBigObject('foo bar'));
console.timeEnd('perf');
#include <napi.h>

Napi::Value GetBigObject(const Napi::CallbackInfo& info) {
  Napi::Env m_env = info.Env();

  Napi::Object node = Napi::Object::New(m_env);
  node.Set(Napi::String::New(m_env, "foo"), Napi::Number::New(m_env, 1));
  node.Set(Napi::String::New(m_env, "body"), Napi::Array::New(m_env));


  for (int i = 0; i < 2000000; i++) {
    Napi::Object stmt = Napi::Object::New(m_env);
    stmt.Set(Napi::String::New(m_env, "foo"), Napi::Number::New(m_env, 1));
    Napi::Array body = node.Get("body").As<Napi::Array>();
    auto len = std::to_string(body.Length());
    body.Set(Napi::String::New(m_env, len), stmt);
  }


  return node;
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports.Set(Napi::String::New(env, "getBigObject"), Napi::Function::New(env, GetBigObject));
  return exports;
}

NODE_API_MODULE(addon, Init)

Running this code time cost:

perf: 2.782s

pure-js case:

var addon = require('./addon.js');

console.time('perf');
console.log('This should be result:', addon.getBigObject('var foo = 1;'));
console.timeEnd('perf');
module.exports.getBigObject = function() {
  const node = {};
  node.foo = 1;
  node.body = [];
  for (let i = 0; i < 2000000; i++) {
    let body = node.body;
    body.push({
      foo: 1
    });
  }
  return node;
}

Running this code time cost:

perf: 220.973ms

Why is this so slow that generate JsObject in cpp-addon? Perhaps it is relative to V8 Hidden-Class? How could I generate JsObject in cpp-addon faster?

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

(V8 developer here.)

Why is this so slow that generate JsObject in cpp-addon?

In short: because in JavaScript, you benefit from engine optimizations; whereas in C++, you have to optimize things yourself.

How could I generate JsObject in cpp-addon faster?

The general answer to "how can I make anything faster?" is: profile it to see where exactly the time is spent, and then see if you can avoid or optimize that.

Based on your code, I can make a few guesses at things that may be worth trying:

for (int i = 0; i < 2000000; i++) {

That is a huge iteration count; creating so many handles (in the loop body) in a single HandleScope is probably contributing to the slowness. I'd use a nested loop to create a new HandleScope in the outer loop for every 1000 or so iterations of the inner loop. See here.

Napi::Object stmt = Napi::Object::New(m_env);
stmt.Set(Napi::String::New(m_env, "foo"), Napi::Number::New(m_env, 1));

The V8 API has the ObjectTemplate system to churn out fresh copies of similar-looking objects as quickly as possible. It looks like N-API doesn't expose that though; so you could either move from N-API to using the V8 API directly, or simply live without it, hoping that it wouldn't make too much of a difference.

Napi::Array body = node.Get("body").As<Napi::Array>();

Reading the "body" property of node in every iteration is unnecessary, as you know that it'll return the array you allocated previously, so just cache that in a local variable.

auto len = std::to_string(body.Length());

Reading the length in every iteration is unnecessary, as it's always identical to i.

body.Set(Napi::String::New(m_env, len), stmt);

Creating a string for an array index just to force the engine to convert that string back to a number is quite inefficient. napi_set_element avoids the unnecessary back-and-forth.

Another thing that the V8 API lets you do (but I can't find it on the N-API documentation) is compiling and executing any JS code you want. So if you really want the exact equivalent of the JS snippet, you can just call that JS snippet. (To save recompilation effort, I'd compile it as a separate step and cache the resulting function if you intend to call it repeatedly.)

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda