brpc/docs/cn/iobuf.md
2022-12-14 20:13:26 +08:00

104 lines
2.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[English version](../en/iobuf.md)
brpc使用[butil::IOBuf](https://github.com/brpc/brpc/blob/master/src/butil/iobuf.h)作为一些协议中的附件或http body的数据结构它是一种非连续零拷贝缓冲在其他项目中得到了验证并有出色的性能。IOBuf的接口和std::string类似但不相同。
如果你之前使用Kylin中的BufHandle你将更能感受到IOBuf的便利性前者几乎没有实现完整直接暴露了内部结构用户得小心翼翼地处理引用计数极易出错。
# IOBuf能做的
- 默认构造不分配内存。
- 可以拷贝修改拷贝不影响原IOBuf。拷贝的是IOBuf的管理结构而不是数据。
- 可以append另一个IOBuf不拷贝数据。
- 可以append字符串拷贝数据。
- 可以从fd读取可以写入fd。
- 可以解析或序列化为protobuf messages.
- IOBufBuilder可以把IOBuf当std::ostream用。
# IOBuf不能做的
- 程序内的通用存储结构。IOBuf应保持较短的生命周期以避免一个IOBuf锁定了多个block (8K each)。
# 切割
从source_buf头部切下16字节放入dest_buf
```c++
source_buf.cut(&dest_buf, 16); // 当source_buf不足16字节时切掉所有字节。
```
从source_buf头部弹掉16字节
```c++
source_buf.pop_front(16); // 当source_buf不足16字节时清空它
```
# 拼接
在尾部加入另一个IOBuf
```c++
buf.append(another_buf); // no data copy
```
在尾部加入std::string
```c++
buf.append(str); // copy data of str into buf
```
# 解析
解析IOBuf为protobuf message
```c++
IOBufAsZeroCopyInputStream wrapper(&iobuf);
pb_message.ParseFromZeroCopyStream(&wrapper);
```
解析IOBuf为自定义结构
```c++
IOBufAsZeroCopyInputStream wrapper(&iobuf);
CodedInputStream coded_stream(&wrapper);
coded_stream.ReadLittleEndian32(&value);
...
```
# 序列化
protobuf序列化为IOBuf
```c++
IOBufAsZeroCopyOutputStream wrapper(&iobuf);
pb_message.SerializeToZeroCopyStream(&wrapper);
```
用可打印数据创建IOBuf
```c++
IOBufBuilder os;
os << "anything can be sent to std::ostream";
os.buf(); // IOBuf
```
# 打印
可直接打印至std::ostream. 注意这个例子中的iobuf必需只包含可打印字符。
```c++
std::cout << iobuf << std::endl;
// or
std::string str = iobuf.to_string(); // 注意: 会分配内存
printf("%s\n", str.c_str());
```
# 性能
IOBuf有不错的综合性能
| 动作 | 吞吐 | QPS |
| ---------------------------------------- | ----------- | ------- |
| 文件读入->切割12+16字节->拷贝->合并到另一个缓冲->写出到/dev/null | 240.423MB/s | 8586535 |
| 文件读入->切割12+128字节->拷贝->合并到另一个缓冲->写出到/dev/null | 790.022MB/s | 5643014 |
| 文件读入->切割12+1024字节->拷贝->合并到另一个缓冲->写出到/dev/null | 1519.99MB/s | 1467171 |