鸿蒙Next:JSArray 和ArrayBuffer 谁的性能好?

197 阅读2分钟

如果项目中你要存储int32类型的数组,并且要对其进行操作,JSArray 和ArrayBuffer 谁的性能好?

研究发现

napi_create_arraybuffer等同于JS代码中的new ArrayBuffer(size),其生成的对象不可直接在TS/JS中进行读取,需要将其包装为TyppedArray或DataView后方可进行读写。

基准性能测试结果如下:

说明:以下数据为千次循环写入累计数据,为更好的体现出差异,已对设备核心频率进行限制。

容器类型Benchmark数据(us)
JSArray1566.174
ArrayBuffer3.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;
}