Skip to content

Latest commit

 

History

History
97 lines (67 loc) · 2.77 KB

iobuf.md

File metadata and controls

97 lines (67 loc) · 2.77 KB

brpc uses butil::IOBuf as data structure for attachment storage and HTTP body. It is a non-contiguous zero copy buffer, which has been proved in other projects as excellent performance. The interface of IOBuf is similar to std::string, but not the same.

If you used the BufHandle in Kylin before, you should notice the difference in convenience of IOBuf: the former hardly had any encapsulation, leaving the internal structure directly in front of the user. The user must carefully handle the reference count, which is very error prone, leading to lots of bugs.

What IOBuf can:

  • Default constructor doesn't involve copying.
  • Explicit copy doesn't change source IOBuf. Only copy the management structure of IOBuf instead of the data.
  • Append another IOBuf without copy.
  • Append string involves copy.
  • Read from/Write into fd.
  • Convert to protobuf and vice versa.
  • IOBufBuilder可以把IOBuf当std::ostream用。

What IOBuf can't:

  • Used as general storage structure. IOBuf should not keep a long life cycle to prevent multiple memory blocks (8K each) being locked by one IOBuf object.

Slice

Slice 16 bytes from IOBuf:

source_buf.cut(&heading_iobuf, 16); // cut all bytes of source_buf when its length < 16

Remove 16 bytes:

source_buf.pop_front(16); // Empty source_buf when its length < 16

Concatenate

Append to another IOBuf:

buf.append(another_buf);  // no data copy

Append std::string

buf.append(str);  // copy data of str into buf

Parse

Parse protobuf from IOBuf

IOBufAsZeroCopyInputStream wrapper(&iobuf);
pb_message.ParseFromZeroCopyStream(&wrapper);

Parse IOBuf as user-defined structure

IOBufAsZeroCopyInputStream wrapper(&iobuf);
CodedInputStream coded_stream(&wrapper);
coded_stream.ReadLittleEndian32(&value);
...

Serialize

Serialize protobuf into IOBuf

IOBufAsZeroCopyOutputStream wrapper(&iobuf);
pb_message.SerializeToZeroCopyStream(&wrapper);

Append printable data into IOBuf

IOBufBuilder os;
os << "anything can be sent to std::ostream";
os.buf();  // IOBuf

Print

std::cout << iobuf;
std::string str = iobuf.to_string();

Performance

IOBuf has excellent performance in general aspects:

Action Throughput QPS
Read from file -> Slice 12+16 bytes -> Copy -> Merge into another buffer ->Write to /dev/null 240.423MB/s 8586535
Read from file -> Slice 12+128 bytes -> Copy-> Merge into another buffer ->Write to /dev/null 790.022MB/s 5643014
Read from file -> Slice 12+1024 bytes -> Copy-> Merge into another buffer ->Write to /dev/null 1519.99MB/s 1467171