< 返回版块

苦瓜小仔 发表于 2025-08-15 14:34

Tags:日报

Sdr-podcast:侵入式链表的乐趣和收益

播客《Intrusive lists for fun and profit》用 60 分钟讲透“嵌入式 Rust 为什么要用侵入式链表、怎么用、怎么做得安全”。

  1. 经典链表 vs 侵入式链表
    • 经典:节点和数据各一次分配,两倍指针跳转,缓存不友好。
    • 侵入:把“前后指针”直接塞进数据体里,一次分配零额外内存,可在 无堆(no-alloc) 场景使用。

  2. 嵌入式场景刚好把“链表缺点”变成优点
    MCU SRAM 极小且无缓存层级,线性遍历或随机跳转代价几乎相同;反而 Vec 需要 realloc,在 无 alloc 环境里根本用不起。

  3. 没有 Vec 怎么“可变长”
    上限集合(heapless::Vec、const-generic 数组)或把节点直接放进任务静态存储,编译期就能算出总内存,溢出直接编译报错。

  4. Pin + 侵入链表 = 安全可变长零分配
    • 每个任务内部放一个 Node(含前后指针+负载)。
    • 任务被 pin! 住,Node 地址绝不移动;drop 时自动把自己从链表摘掉。
    • 整个列表只需一把阻塞互斥锁即可保证并发安全。
    → James 把这一套封装成 pin-list crate:用户写 零 unsafe 代码即可用。

  5. 实战案例
    cfg-noodle:配置项分散在各任务,统一由后台 IO Worker 遍历链表做持久化。
    ergot:嵌入式网络栈,Socket 作为节点挂在全局链表,收包线程按表投递。
    • 两套库都靠 cordyceps(侵入链表底层实现)+ mutex(临界区锁)支撑,依赖树极浅。

  6. 什么时候该用
    无 alloc、内存上限必须静态可证、需要“可变数量对象”同时保持确定性——就把侵入式链表放进你的工具箱;其余场景仍优先 Vec/VecDeque。

收听/文字稿:https://sdr-podcast.com/episodes/intrusive-lists-for-fun-and-profit/#transcript

Slides:https://sdr-podcast.com/slides/2025-08-13-intrusive-lists-for-fun-and-profit.pdf

Snakeshell:终端内的贪吃蛇游戏

仓库:https://github.com/iShibi/snakeshell

Serde-ply:90 年代格式的现代速度和便利性

刚刚发布了我的第一个 crate!虽然 ply 文件是 90 年代的一种格式,但它们在计算机图形学中仍然非常流行,并且不知何故成为了“高斯分布”的标准(无耻的宣传)。Rust 生态系统有一个用于 ply 文件的 crate,但在我的测试中,它比 serde-ply 慢了大约 4-7 倍。

serde-ply 目标是获得所有现代 serde 的便利,同时又不牺牲太多的性能(达到约 1 GB/s,与其他库一致)。

由于 Ply 文件本质上是一个大型“表格”,因此也可以逐行流式传输结果。我添加了一些方法来以“块”的形式读取 Ply 文件。这些数据块也可以来自 async 读取器,因此虽然该库没有异步代码,但它兼容 async 读取。

仓库:https://github.com/ArthurBrussee/serde_ply

Reddit:https://www.reddit.com/r/rust/comments/1mp147s/serdeply_modern_speed_convenience_for_a_90s_format/

derive_hash_fast:哈希速度比 #[derive(Hash)] 快 2 倍以上

TL;DR: #[derive(Hash)] 会逐个对结构体字段进行哈希处理,这会影响性能。derive_hash_fast 一次性对整个结构体进行哈希处理,速度要快得多。对于大切片,差异更加明显,性能提升超过 10 倍。

限制: 结构体必须能够安全地被视为字节切片。这可以通过要求派生自 bytemuckzerocopy trait 来强制执行,具体方法由您自行选择。

此 crate 的灵感源自 @purplesyringa (他与此 crate 无关)的精彩博文 。您可以阅读该博文,深入了解 #[derive(Hash)] 以及 Hash trait 的常见问题。

我们通过以下方式实现了比 #[derive(Hash)] 更好的性能:

  • 一次性对整个结构进行哈希处理(而不是单独对每个字段进行哈希处理)
  • 分派到一系列原始写入操作,例如在编译时确定的 hasher.write_u64 ,并在必要时进行填充(而不是在哈希器中使用缓慢的可变长度代码路径)
  • 复制 std 对 u8 和其他原始类型在切片中执行的优化,以便例如 &[MyType(u8)] 可以像 &[u8] 一样快速进行哈希处理。这也适用于具有多个字段的结构体。

用法:

仓库:https://github.com/Shnatsel/rust_derive_hash_fast

Reddit:https://www.reddit.com/r/rust/comments/1mo8z2c/derive_hash_fast_over_2x_faster_hashing_than/

--

From 日报小组 苦瓜小仔

社区学习交流平台订阅:

评论区

写评论

还没有评论

1 共 0 条评论, 1 页