我正在尝试将JS算法移植到C ++,看看我是否可以提高性能,但是我在填充v8阵列时遇到了巨大的性能瓶颈。
这是一个仅重现填充数组的代码段。我创建了一个包含800个项目的数组,每个项目是一个包含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)
}
答案 0 :(得分:1)
从C ++创建JS对象(并与它们交互)比从JS中创建JS对象更昂贵。这很容易抵消其余C ++代码的性能提升。
您可以通过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
数据(char *
)的引用,并在工作线程中填充它(请参阅nan
的{{3}为了一个方便的帮助者。)
答案 1 :(得分:0)
正如mtth所说,在C ++中使用JS数组是很昂贵的。使用缓冲区可以工作,但您也可以使用TypedArrays。这些可以从C ++访问,作为连续,对齐的内存块的指针,这使得它们易于使用并且可以快速迭代。
有关如何访问其内容的一些信息,请参阅https://stackoverflow.com/a/31712512/1218408。