#collection #slot #generational #structure #id #order #unique

alot

一个禁止不安全的、使用usize大小的ID的代际槽映射

4个版本 (2个破坏性版本)

0.3.1 2023年12月2日
0.3.0 2023年7月25日
0.2.0 2023年6月21日
0.1.0 2023年5月3日

#339数据结构

Download history 32/week @ 2024-03-11 43/week @ 2024-03-18 90/week @ 2024-03-25 118/week @ 2024-04-01 114/week @ 2024-04-08 20/week @ 2024-04-15 40/week @ 2024-04-22 57/week @ 2024-04-29 204/week @ 2024-05-06 53/week @ 2024-05-13 43/week @ 2024-05-20 25/week @ 2024-05-27 53/week @ 2024-06-03 31/week @ 2024-06-10 253/week @ 2024-06-17 29/week @ 2024-06-24

370 每月下载
3 crate 中使用

MIT/Apache

48KB
1K SLoC

alot

alot forbids unsafe code alot is considered alpha crate version Live Build Status HTML Coverage Report for main Documentation for main

一组用于使用生成的唯一键在类似映射的结构中存储值的集合。基本集合类型 Lots<T> 为每个存储的值返回一个 LotId。可以使用这些 LotId 来检索或删除存储的值。

此集合提供的插入和读取性能与 Vec<T> 相当,但不保证包含值的顺序。

如果需要排序,提供 OrderedLots<T>,它跟踪元素的顺序,同时仍然允许通过 LotId 进行查找。通过 LotId 删除值成为此集合的 O(n) 操作。

Lots<T>:T的无序集合

use alot::Lots;

let mut map = Lots::new();
// Similar to a Vec, push adds a new value to the collection.
let greeting = map.push("hello, world");
// Prints: Greeting: LotId { generation: 1, index: 0 }
println!("Greeting: {greeting:?}");
// Values can be retrieved by their LotId.
assert_eq!(map[greeting], "hello, world");

OrderedLots<T>:T的有序集合

use alot::OrderedLots;

let mut map = OrderedLots::new();
// Values stored in OrderedLots can be accessed by index or by their LotId.
let c = map.push("c");
let a = map.push("a");

assert_eq!(map[c], map[0]);

// With OrderedLots, values can be inserted as well as pushed.
let b = map.insert(1, "b");
assert_eq!(map, &["c", "b", "a"]);

// OrderedLots also provides sorting functions.
map.sort();
assert_eq!(map, &["a", "b", "c"]);

这个crate与其它crate有什么不同?

有几种“槽映射”或“代际竞技场”或其他类似名称的结构方法。这个crate采用了两种独特的方法

  • 没有不安全代码。
  • LotId 是一个单一的 usize。大多数槽映射使用 usize 作为索引,并使用另一个 usize 作为代。
  • 在内部,每个值的存储空间只有最多2字节的开销,不包括编译器可能添加的填充。大多数代际映射必须存储一个 usize 作为代,并且许多由于使用 Option<T> 而产生额外的1字节开销。
  • 空闲列表是一个 Vec<usize>,而不是尝试重用空槽的空间。这样做是为了以下优势
    • 在没有64位架构上的 unsafe 的情况下,如果没有造成 SlotData 枚举比目前在使用 size_of::<T> 时占用更多空间的情况下,是无法将48位的索引数据放入Empty状态的。例如,Lots<u16> 的内部槽存储每个值使用4个字节。
    • 除非收集被清空或进行大量删除操作,否则空闲列表通常较短。

这些设计选择导致了此实现的一些限制

  • 集合限制在最大 usize 的75%。通常,这并不是一个真正的限制,因为分配一个跨越目标架构RAM 75%的连续内存区域并不实际。在64位平台上,Lots<T> 可以容纳2^48个项目 - 281万亿个项目。
  • 与使用完整的 usize 为代数的实现相比,此实现由于代数的旋转,更有可能返回过时的ID数据。
  • 在大多数情况下,集合先变得很大然后又变得非常小,将比使用链表方法跟踪空闲槽的替代解决方案使用更多的RAM。

无运行时依赖