6个版本
0.2.4 | 2022年11月6日 |
---|---|
0.2.3 | 2022年2月17日 |
0.1.0 | 2022年2月8日 |
#711 在 数据结构
105KB
2.5K SLoC
ParallelVec
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