[英]Node.JS performance vs native C++ addon when populating an Int32Array
我一直在嘗試使用Node.JS和C ++插件,發現在使用C ++插件時填充Int32Array要慢得多,而不是在Node.JS / JavaScript中直接填充。
Node.JS:133~ms
C ++:1103~ms
有人知道為什么嗎? 我的測試代碼包含了相當大陣和含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 ++代碼中使用的函數是V8函數,並不是我自己定義的。 有沒有其他方法在Int32Array中設置值而不使用它們?
我並不感到驚訝,這寫得很慢,但你可以做很多事情來加速它。 關鍵的見解是,當在節點中處理JavaScript類型的數組時,您可以訪問內存緩沖區並直接對其進行操作。
雖然在處理普通的JavaScript數組/對象時,以下是必要的
整數::新( 隔離 , 值 )
和
testArray-> Set( value )
例如,以下行
testArray->Set(i, Integer::New(isolate, 0));
創建一個新的Number對象,將整數0轉換為double,因為所有JavaScript數都是double,使用Number對象調用Set ,然后將double轉換回整數,因為它將值存儲在Int32類型的數組中,然后析構數字對象。 這發生了300萬次。
但是類型化數組是不同的,並且調用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);
}
用上面的代替可以讓事情變得更快,但是測試需要多快。 可以克隆以下包,並在運行時(使用節點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)
換句話說,簡單地分配數組在JavaScript中大約需要60ms,在C ++模塊中需要80ms。 但這意味着剩下的時間是在循環中花費的時間,在C ++中約為60ms,在Javascript中約為110ms。 因此,對於主要使用直接緩沖區訪問進行循環和計算的操作,首選C ++。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.