如果项目中你要存储int32类型的数组,并且要对其进行操作,JSArray 和ArrayBuffer 谁的性能好?
研究发现:
napi_create_arraybuffer等同于JS代码中的new ArrayBuffer(size),其生成的对象不可直接在TS/JS中进行读取,需要将其包装为TyppedArray或DataView后方可进行读写。
基准性能测试结果如下:
说明:以下数据为千次循环写入累计数据,为更好的体现出差异,已对设备核心频率进行限制。
| 容器类型 | Benchmark数据(us) |
|---|---|
| JSArray | 1566.174 |
| ArrayBuffer | 3.609 |
使用高性能数组
【建议】 存储值类型数据时,使用ArrayBuffer代替JSArray来提高应用性能。
使用JSArray作为容器储存数据,支持几乎所有的JS数据类型。
使用napi_set_element方法对JSArray存储值类型数据(如int32)时,同样会涉及到与运行时的交互,造成不必要的开销。
ArrayBuffer进行增改是直接对缓冲区进行更改,具有远优于使用napi_set_element操作JSArray的性能表现。
因此此种场景下,更推荐使用napi_create_arraybuffer接口创建的ArrayBuffer对象。
示例
// 以下代码使用常规JSArray作为容器,但其仅存储int32类型数据。
// 但因为是JS对象,因此只能使用napi方法对其进行增改,性能较低。
static napi_value ArrayDemo(napi_env env, napi_callback_info info)
{
constexpr size_t arrSize = 1000;
napi_value jsArr = nullptr;
napi_create_array(env, &jsArr);
for (int i = 0; i < arrSize; i++) {
napi_value arrValue = nullptr;
napi_create_int32(env, i, &arrValue);
// 常规JSArray使用napi方法对array进行读写,性能较差。
napi_set_element(env, jsArr, i, arrValue);
}
return jsArr;
}
// 推荐写法:
// 同样以int32类型数据为例,但以下代码使用ArrayBuffer作为容器。
// 因此可以使用C/C++的方法直接对缓冲区进行增改。
static napi_value ArrayBufferDemo(napi_env env, napi_callback_info info)
{
constexpr size_t arrSize = 1000;
napi_value arrBuffer = nullptr;
void* data = nullptr;
napi_create_arraybuffer(env, arrSize * sizeof(int32_t), &data, &arrBuffer);
int32_t* i32Buffer = reinterpret_cast<int32_t*>(data);
for (int i = 0; i < arrSize; i++) {
// arrayBuffer直接对缓冲区进行修改,跳过运行时,
// 与操作原生C/C++对象性能相当
i32Buffer[i] = i;
}
return arrBuffer;
}