当填充Int32Array时,Node.JS性能与本机C ++插件相比

我一直在尝试使用Node.JS和C ++插件,发现在使用C ++插件时,填充Int32Array比在Node.JS / JavaScript中直接插入要慢得多。

Node.JS:133〜ms
C ++:1103〜ms

有人知道为什么吗? 我的testing代码由一个相当大的数组和包含if语句的循环组成。

我怀疑我正在我的C ++插件中错误地填充数组。 (?)

JavaScript的:

var testArray = new Int32Array(36594368); var i = 0; for (var xi = 0; xi < 332; xi++) { for (var yi = 0; yi < 332; yi++) { for (var zi = 0; zi < 332; zi++) { if ((xi + yi + zi) % 62 == 0) testArray[i] = 2; else if (yi < 16) testArray[i] = 2; else if (yi == 16) testArray[i] = 1; else testArray[i] = 0; i++; } } } 

C ++插件:

 Local<Int32Array> testArray = Int32Array::New(ArrayBuffer::New(isolate, 4 * 36594368), 0, 36594368); int i = 0; for (int xi = 0; xi < 332; xi++) { for (int yi = 0; yi < 332; yi++) { for (int zi = 0; zi < 332; zi++) { if ((xi + yi + zi) % 62 == 0) testArray->Set(i, Integer::New(isolate, 2)); else if (yi < 16) testArray->Set(i, Integer::New(isolate, 2)); else if (yi == 16) testArray->Set(i, Integer::New(isolate, 1)); else testArray->Set(i, Integer::New(isolate, 0)); i++; } } } 

编辑:只是添加,我在我的C代码中使用的function是V8function,并没有自己定义。 有没有另一种方法来设置Int32Array中的值而不使用这些?

使用C ++最大化types化数组的性能

我并不感到惊讶,这是书面的缓慢​​,但有很多,你可以做,以加快速度。 关键的洞察是,当处理节点中的JavaScripttypes数组时,可以访问内存缓冲区并直接对其进行操作。

慢的主要来源

虽然在处理正常的JavaScript数组/对象时,以下是必要的

整数::新( 隔离

testArray-> Set( value

所以例如下面一行

 testArray->Set(i, Integer::New(isolate, 0)); 

创build一个新的Number对象,将整数0转换为double,因为所有JavaScript数字都是double,使用Number对象调用Set ,然后将double转换为整数,因为它将值存储在Int32types的数组中,然后破坏数字对象。 这发生了300万次。

一种提升

但是types化数组是不同的,调用GetIndexedPropertiesExternalArrayData可以访问底层缓冲区,对于Int32Array来说,这个缓冲区是int的缓冲区。 这允许C ++函数被重写,以避免所有这些分配和强制转换:

 void doMkArray(const FunctionCallbackInfo<Value> &args) { v8::Isolate *I = v8::Isolate::GetCurrent(); Local<Int32Array> testArray = Int32Array::New(ArrayBuffer::New(I, 4 * 36594368),0,36594368); int *dptr = (int*)testArray->GetIndexedPropertiesExternalArrayData(); int i = 0; for (int xi = 0; xi < 332; xi++) { for (int yi = 0; yi < 332; yi++) { for (int zi = 0; zi < 332; zi++) { if ((xi + yi + zi) % 62 == 0) dptr[i] = 2; else if (yi < 16) dptr[i] = 2; else if (yi == 16) dptr[i] = 1; else dptr[i] = 0; i++; } } } args.GetReturnValue().Set(testArray); } 

一些测量

用上面的代替使得事情变得更快,但是要多快才需要一个testing。 以下软件包可被克隆,运行时(使用节点0.12.5)会导致以下结果

  Performance Tests ✓ via javascript (169ms) ✓ via c++ (141ms) 

所以,单独使用C ++的速度会更快,但也许并不是那么令人惊奇,但是如果Javascript和C ++循环(请参见src)都被注释掉,并且只包含数组分配:

  void doMkArray(const FunctionCallbackInfo<Value> &args) { v8::Isolate *I = v8::Isolate::GetCurrent(); Local<Int32Array> testArray = Int32Array::New(ArrayBuffer::New(I, 4 /* ... 

然后时间改变

  Performance Tests ✓ via javascript (62ms) ✓ via c++ (80ms) 

换句话说,简单地分配数组需要大约60ms的JavaScript和80ms的C ++模块。 但是这意味着剩下的时间就是在循环中花费的时间,在C ++中约为60ms,在Javascript中约为110ms。 对于主要是使用直接缓冲区访问的循环和计算的操作,C ++是首选。