golang bytes数组转io.writer_Rust并发:bytes源码分析

bytes库Rust网络编程中使用比较频繁,其提供了和字节数组相关的一组抽象,能够极大避免内存拷贝。提供的主要组件如下:

  1. Bytes结构: 底层封装了一段连续的内存,提供了引用计数跟踪内存的生命周期,类似 &'static [u8],可供多个实例共享。
  2. Buf/BufMut trait: 对逻辑上连续,但是底层表示可能不连续的Buffer抽象,分别类似 &[&[u8]]&[&mut[u8]]
  3. BytesMut结构:封装了一段可以修改但是后续可以生成Bytes共享出去的的连续内存。

下面主要对Bytes进行分析,Buf/BufMut本身只是trait定义,一看就懂;为减少API,加快稳定,后面可能会移除掉BytesMut,所以有空再作分析。

Bytes内存布局

下面是Bytes的大致内存布局图。底层的连续内存使用引用计数,每个实例持一个引用,以及记录本身所占有的区间。

ea4bfc2decccffdab9240b05e321b8ad.png
Bytes的结构布局

最简单的实现差不多是:

struct Bytes {
    
    raw: Arc<[u8]>,
    data: usize,
    len: usize,
}

不过考虑到还有两类可优化的情况:

  1. 底层的内存来自于 &'static [u8],那么本身就是可共享的,拷贝进Arc里,再进行引用计数,太浪费。
  2. 底层的内存来自 Vec<u8>或者 Box<[u8]>,且还没有发生共享只有一个Bytes实例的情况,如果这种情况能优化掉,那么Bytes的使用开销和Vec就几乎无差别了。

对这两种情况的优化是Bytes的主要看点。

Bytes结构定义

要考虑到底层内存的多样性,必然要使用多态。Bytes采用自定义虚表的方式实现多态。

pub struct Bytes {
    
    // Bytes可访问的起始地址
    ptr: *const u8, 
    // Bytes可访问的数据长度
    len: usize,     
    // 底层的对象指针
    data: AtomicPtr<()>, 
    // 底层对象的虚表指针
    vtable: &'static Vtable, 
}

pub(crate) struct Vtable {
    
    /// fn(data, ptr, len)
    pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Bytes,
    /// fn(data, ptr, le
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值