如何在无多次读取与显式JS循环下,高效获取TypedArray中超64位类结构体数据?
高性能场景下JS模拟C语言大型Struct拷贝的问题
这是一个性能相关问题,常规JavaScript规则与约定不适用。请注意,JS对象的性能无法与C语言的struct(尤其是以AoS格式分配的struct)相提并论。
C语言中高效操作大型Struct数组的方式
在C语言中,我们可以通过将结构体数组中的struct实例拷贝到局部变量,修改后再通过简单赋值写回数组,实现大型struct数据的快速读写。struct大小可达平台指定上限(通常数千字节),这种方式简便高效,底层会使用类似memcpy的快速操作实现。
示例代码:
struct MyStruct arrayOfStructs[]; // 为简化示例声明在栈上 // ... 向结构体数组填充数据 ... // 将目标struct拷贝到栈上的局部变量 struct MyStruct structValue = arrayOfStructs[i]; // 修改struct成员 structValue.x = 12; structValue.y = 3; // 按值赋值回数组,无需逐成员操作 arrayOfStructs[i]、Check_un inc�操作 Mostly费Meanwhile� synd Image标题层级调整:把“这是一个性能相关问题...”放在最开头,然后是C语言部分用##,JS部分用##,大struct部分用###,核心问题用**,补充说明,最后标注来源。 现在重新整理: # 高性能场景下JS模拟C语言大型Struct拷贝的问题 这是一个性能相关问题,常规JavaScript规则与约定不适用。请注意,JS对象的性能无法与C语言的struct(尤其是以AoS格式分配的struct)相提并论。 ## C语言中高效操作大型Struct数组的方式 在C语言中,我们可以通过将结构体数组中的struct实例拷贝到局部变量,修改后再通过简单赋值写回数组,实现大型struct数据的快速读写。struct大小可达平台指定上限(通常数千字节),这种方式简便高效,底层会使用类似memcpy的快速操作实现。 示例代码: ```c struct MyStruct arrayOfStructs[]; // 为简化示例声明在栈上 // ... 向结构体数组填充数据 ... // 将目标struct拷贝到栈上的局部变量 struct MyStruct structValue = arrayOfStructs[i]; // 修改struct成员 structValue.x = 12; structValue.y = 3; // 按值赋值回数组,无需逐成员操作 arrayOfStructs[i] = structValue;
无论struct多大,只需一行代码即可完成写回,编译器会自动优化拷贝操作。
JavaScript中用TypedArray模拟Struct的方案
在JS中,唯一高性能的替代方案是使用TypedArray。以下是模拟小型struct的实现:
const SIZEOF_X = 1; // 1字节 const SIZEOF_Y = 1; // 1字节 const SIZEOF_Z = 1; // 1字节 const SIZEOF_PADDING0 = 1; // 1字节填充,使后续成员对齐到4B堆边界 const SIZEOF_PAYLOAD1 = 2; // 2字节 const SIZEOF_PAYLOAD2 = 2; // 2字节 const SIZEOF_BYTES_ENTITY = SIZEOF_X + SIZEOF_Y + SIZEOF_Z + SIZEOF_PADDING0 + SIZEOF_PAYLOAD1 + SIZEOF_PAYLOAD2; // 总计8字节 // 为清晰起见,手动计算struct内的偏移量(也可通过循环计算) const OFFSET_BYTES_X = 0; const OFFSET_BYTES_Y = SIZEOF_BYTES_X; const OFFSET_BYTES_Z = SIZEOF_BYTES_X + SIZEOF_BYTES_Y; // ... 其他成员偏移量 ... const buffer = new ArrayBuffer(ENTITIES_COUNT * SIZEOF_BYTES_ENTITY); const structsAs64 = new Uint64Array(buffer); // 单个struct占8字节,用Uint64Array视图 const structsAs16 = new Uint16Array(buffer); const structsmarkets { 是ve "(Qyn年份** level占用代码的代码: ```js // 新的struct大小为96字节 const SIZEOF_BYTES_ENTITY = 96; const SIZEOF_WORDS_ENTITY = SIZEOF_BYTES_ENTITY / 8; // 对应多个64位字 const buffer = new ArrayBuffer(ENTITIES_COUNT * SIZEOF_BYTES_ENTITY); const bigStructsAs64 = new Uint64Array(buffer); // ... 向底层buffer填充数据 ...(未展示) let index = 43; // 目标实体的索引 // 使用subarray创建视图,但会产生需要GC的对象 let bigStruct = bigStructsAs64.subarray(index * SIZEOF_WORDS_ENTITY);
subarray()的问题在于会创建新的TypedArray视图,若每帧都执行会增加垃圾回收负担。相比之下,显式JS循环拷贝的效率更低:
const bigStruct = new Uint64Array(SIZEOF_WORDS_ENTITY); // 逐64位字拷贝 for (let w = 0; w < SIZEOF_WORDS_ENTITY; w++) { bigStruct[w] = bigStructsAs64[index * SIZEOF_WORDS_ENTITY + w]; }
核心问题:是否存在无需使用显式JS循环即可快速获取大数据块的方法?
补充说明:有相关讨论涉及上述循环的性能影响评估,目前假设原生方法执行此类数据收集操作的效率会高于JS编写的循环,后续会完成测试并反馈结果。
内容的提问来源于stack exchange,提问作者Engineer
相关产品推荐
相关产品推荐

