1

我正在尝试将 JS 算法移植到 C++,看看我是否可以提高性能,但我在填充 v8 数组时面临着巨大的性能瓶颈。

这是一个仅复制填充数组的片段。我创建了一个包含 800k 个项目的数组,每个项目都是一个包含 17 个数字的数组。这个算法在我的机器上执行需要 3 秒,这是相当大的。

有没有办法加快速度?

#include <node.h>

namespace demo {

  using namespace v8; // just for lisibility of the example

  void Method(const FunctionCallbackInfo<Value>& args) {
    Isolate* isolate = args.GetIsolate();
    Local<Array> array = Array::New(isolate, 800000);

    for (int i = 0; i < 800000; ++i) {
      Local<Array> line = Array::New(isolate, 17);

      for (int j = 0; j < 17; ++j) {
        line->Set(j, Number::New(isolate, i * 100 + j));
      }

      array->Set(i, line);
    }

    args.GetReturnValue().Set(array);
  }

  void Init(Local<Object> exports) {
    NODE_SET_METHOD(exports, "hello", Method);
  }

  NODE_MODULE(parser, Init)

}
4

2 回答 2

1

从 C++ 创建 JS 对象(并与它们交互)比从 JS 中创建更昂贵。这可以轻松抵消其余 C++ 代码带来的性能提升。

您可以通过 a 进行通信来解决此问题Buffer(序列化开销通常低于上述)。更重要的是,这还可以让您完成 v8 主线程的工作。

Buffer.readIntLE如果您只处理数字,则使用(或类似方法)应该相对简单。您还可以将数组的长度编码到缓冲区的前几个字节中。以下是 JS 方面的情况:

var buf = new Buffer(/* Large enough to contain your serialized data. */);

// Function defined in your C++ addon.
addon.populate(buf, function (err) {
  if (err) {
    // Handle C++ error.
    return;
  }
  // At this point, `buf` contains the serialized data. Deserialization
  // will depend on the chosen serialization format but a reasonable
  // option could be the following:
  var arr = [];
  var pos = 4;
  var size = buf.readInt32LE(0);
  while (size--) {
    var subarr = new Array(17);
    for (var i = 0; i < 17; i++) {
      subarr[i] = buf.readInt32LE(pos);
      pos += 4;
    }
    arr.push(subarr);
  }
  // `arr` now contains your decoded data.
});

代码的 C++ 部分将保留对buf's 数据 (a char *) 的引用并将其填充到工作线程中(请参阅nan'sAsyncWorker以获得方便的帮助器)。

于 2016-03-21T19:22:32.440 回答
0

正如 mtth 所说,在 C++ 中使用 JS 数组很昂贵。使用缓冲区会起作用,但您也可以使用 TypedArrays。这些可以从 C++ 中作为指向连续、对齐的内存块的指针访问,这使得它们易于使用并且可以快速迭代。

有关如何访问其内容的一些信息,请参阅https://stackoverflow.com/a/31712512/1218408 。

于 2016-09-22T02:38:19.183 回答