6个版本

0.2.4 2022年11月6日
0.2.3 2022年2月17日
0.1.0 2022年2月8日

#711数据结构

MIT/Apache

105KB
2.5K SLoC

ParallelVec

crates.io Documentation License codecov

ParallelVec 是一个与 Vec<(T1, T2, ...)> 类似的API泛型连续存储异构值的集合,但以每个字段单独的切片形式存储数据,使用 数组结构 布局。这种布局的优点是在遍历数据时可能显著提高缓存利用率。

这种方法在游戏引擎中很常见,特别是实体-组件-系统,但适用于任何缓存一致性和内存带宽对性能很重要的地方。

与结构体 Vec 不同,只存储一个长度和容量字段,并为整个数据结构分配一个连续的分配。在重新分配时,结构体 Vec 可能会施加额外的分配压力。 ParallelVec 在每次调整大小时只分配一次。

示例

use parallel_vec::ParallelVec;

// #Some 'entity' data.
struct Position { x: f64, y: f64 }
struct Velocity { dx: f64, dy: f64 }
struct ColdData { /* Potentially many fields omitted here */ }

// Create a vec of entities
let mut entities: ParallelVec<(Position, Velocity, ColdData)> = ParallelVec::new();
entities.push((Position {x: 1.0, y: 2.0}, Velocity { dx: 0.0, dy: 0.5 }, ColdData {}));
entities.push((Position {x: 0.0, y: 2.0}, Velocity { dx: 0.5, dy: 0.5 }, ColdData {}));

// Update entities. This loop only loads position and velocity data, while skipping over
// the ColdData which is not necessary for the physics simulation.
for (position, velocity, _) in entities.iter_mut() {
    *position = *position + *velocity;
}

// Remove an entity
entities.swap_remove(0);

no_std 支持

默认情况下,此crate需要标准库。禁用默认功能可以启用此crate在 #![no_std] 环境中编译。此crate要正常工作,必须有一个设置的全局分配器和堆支持。

serde 支持

ParallelVec 可以序列化,如果它的参数可以序列化。默认情况下这是禁用的。使用 serde 功能启用序列化和反序列化支持。

基准测试

要运行基准测试,请使用 cargo bench。此crate的基准测试直接比较了在小型结构体、大型结构体以及两者的混合上,ParallelVec 和其 Vec 等价物的迭代和 get 性能。

通常情况下,当整个缓冲区可以适应缓存时,ParallelVec 的性能与 Vec 类似。一旦后端存储超过缓存大小,或者存在其他操作竞争缓存空间时,ParallelVec 相比于其 Vec 相当物,迭代速度更高,尤其是元素大小增加时。相反,随着整个缓冲区大小的增加,ParallelVec 的性能相对于其 Vec 相当物有所下降。

依赖项

~170KB