零拷贝
问题
Rust 中如何实现零拷贝?
答案
零拷贝指避免不必要的数据复制,直接使用原始内存中的数据。
切片引用
// ❌ 不必要的拷贝
fn process_bad(data: &str) -> String {
let part = data[0..10].to_string(); // 额外分配
part
}
// ✅ 零拷贝:返回引用
fn process_good(data: &str) -> &str {
&data[0..10] // 无分配
}
bytes crate
use bytes::{Bytes, BytesMut, BufMut};
// Bytes 是引用计数的字节缓冲区
// clone 不复制数据,只增加引用计数
let data = Bytes::from("hello world");
let slice1 = data.slice(0..5); // 零拷贝切割
let slice2 = data.slice(6..11); // 共享底层数据
// BytesMut 用于构建缓冲区
let mut buf = BytesMut::with_capacity(1024);
buf.put_u32(42);
buf.put_slice(b"hello");
let frozen = buf.freeze(); // BytesMut → Bytes(零拷贝)
Cow(写时复制)
use std::borrow::Cow;
fn normalize(input: &str) -> Cow<str> {
if input.contains(' ') {
// 需要修改时才分配
Cow::Owned(input.replace(' ', "_"))
} else {
// 不需要修改,零拷贝返回
Cow::Borrowed(input)
}
}
关于 Cow 的详细内容请参考 Cow。
零拷贝场景总结
| 技术 | 场景 |
|---|---|
&str / &[u8] | 只读访问 |
Cow<str> | 可能需要修改 |
Bytes | 网络协议缓冲区 |
mmap | 大文件读取 |
io::copy | 流式数据传输 |
常见面试问题
Q1: Bytes 为什么在网络编程中这么重要?
答案:
网络编程中经常需要将同一个缓冲区的不同部分发送给不同的处理逻辑。Bytes::slice() 是零拷贝的(只增加引用计数),避免了大量不必要的内存复制。tokio 的网络层大量使用 Bytes。