Rust in Everything
基于 bytes 1.12.1

BytesMut

这一部分讲构建主线:一个可写的 BytesMut 怎么在写入、切分、扩容之间尽量不拷贝,最后不拷贝地变成 Bytes。代码在 src/bytes_mut.rs,2.0k 行。写入用的 BufMut 接口在下一部分 Buf 与 BufMut。

三章按「先看结构,再看两种操作」排列:

  1. data 字段的编码:data 最低位区分 KIND_VEC(独占一个 Vec,其余位记 3 位的原始容量和前面切掉的偏移)和 KIND_ARC(指向 Shared);偏移超过 MAX_VEC_POS 时提升;用一个程序把每一步的位打印出来,并看到从 with_capacity(0) 起步的缓冲原始容量是 0。
  2. split 与 freeze:split_to、split_off、split 第一次调用时把 KIND_VEC 提升成 KIND_ARC,计数从 2 开始;freeze 对 KIND_VEC 走 From<Vec<u8>>,对 KIND_ARC 只换一张 vtable;unsplit 和 try_unsplit 何时 O(1)。
  3. reserve:reserve_inner 在 KIND_VEC 时把数据挪回开头或交给 Vec::reserve,在 KIND_ARC 时唯一就原地复用或扩大,不唯一就按 max(需求, 原始容量) 另分配、回到 KIND_VEC;try_reclaim 与 extend_from_within。
flowchart TB
  wc["with_capacity:KIND_VEC"] --> wr["写入:BufMut"]
  wr --> sp["split_to:提升 KIND_ARC"]
  sp --> fz["freeze:交给 Bytes"]
  sp --> rs["reserve"]
  rs -->|唯一| reuse["原地复用"]
  rs -->|还有别人| alloc["另分配:回到 KIND_VEC"]
  reuse --> wr
  alloc --> wr

freeze 之后的 clone、切片和 drop 是共享主线,在 02 Bytes。hyper 的读缓冲就是一个 BytesMut,它怎么用这三章里的操作,见 一块缓冲的一生 和 hyper 卷的 读写缓冲。

💬 关联讨论

发起讨论
加载中...