Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

359
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda