#id-generator #id #unique-id #per-thread #thread #unique #range

no-std tlid

基于预定义范围,无原子操作/锁/随机/时间生成的线程本地 ID

4 个版本

0.2.2 2020年2月5日
0.2.1 2020年2月3日
0.2.0 2020年1月28日
0.1.0 2020年1月26日

#409并发

Apache-2.0 OR MIT

25KB
484

pipeline status coverage report lines of code

TLID

通过为每个线程分配一个范围来实现低级别的唯一 ID 生成。

优点

  • 唯一数字,简单递增
  • 无锁,无原子操作 ::next()
  • 所有依赖都是可选的
  • 速度:600,000,000/s
  • 示例代码
  • 严格的 CI 测试

缺点

  • 范围需要在之前知道,例如 u64,对于 1024 个线程来说,每个线程只能有 2^54 个可用的 ID
  • 不是密码学安全的(简单递增)
  • 池的创建和删除需要同步
  • beta:在 0.9 之前的 tlid 不适合生产环境,可能存在错误或非最佳 ID 返回行为

有很多 ID Crates,但几乎所有都使用一些随机值、时间或原子行为来在多个线程中保持唯一性。Tlid (线程本地唯一 ID) 通过为每个线程分配一个初始范围来旨在实现唯一性。这需要为每个池(和子池)设置一个范围,这使得 ::next() 非常快。

::next() 有 3 种行为选项,不能混合使用

  • 已检查:以每次操作进行范围检查为代价保证唯一 ID
  • 包装:具有相同的检查,但在所有 ID 都使用完毕后,不会使 Pool 无用,而是循环使用。ID 不再唯一,但对于短缓冲区(如网络)很有用
  • 未检查:最快的无保证方法,在 ::next() 方法中不检查边界。

依赖关系

[dependencies]
tlid = "0.2"

示例

// 请参阅 示例 文件夹

use tlid::{Pool, Checked};
use std::{
    thread,
    time::Duration,
    result::Result,
    error::Error,
};

fn worker(thread: u8, p: &mut Pool<Checked<u64>>) {
    //work
    for _ in 0..2 {
        thread::sleep(Duration::from_millis(1));
        println!("[{}] did work: {}", thread, p.next().unwrap());
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    let mut p = Pool::new_full();
    for i in 0..5 {
        let mut local_pool = p.subpool(5)?;
        thread::spawn(move ||
            worker(i, &mut local_pool)
        );
    }
    thread::sleep(Duration::from_millis(100));
    Ok(())
}

示例输出(如您所见,所有 ID 都是唯一的)

[0] did work: 0
[1] did work: 2
[2] did work: 4
[0] did work: 1
[1] did work: 3
[3] did work: 6
[4] did work: 8
[2] did work: 5
[3] did work: 7
[4] did work: 9

许可证

许可方式为以下之一

由您选择。

贡献

除非您明确说明,否则您按照Apache-2.0许可证定义提交的旨在包含在作品中的任何贡献,应按上述方式双许可,不附加任何额外条款或条件。

依赖关系

~95–320KB