当填充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 ++是首选。