अंतिम अद्यतन:2026-10-12
Protobuf ZeroCopy serialization¶
1. ZeroCopyStream¶
protobuf के io interface पर एक ZeroCopyStream है, IO के interface design के लिए, pb ने serialization और deserialization के संबंधित interfaces दिए हैं, जैसे:
// Read a protocol buffer from the given zero-copy input stream. If
// successful, the entire input will be consumed.
bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input);
// Write the message to the given zero-copy output stream. All required
// fields must be set.
bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const;
ZeroCopyStream के design का मूल उद्देश्य buffer की copy की संख्या को न्यूनतम करना है, यानी stream के आंतरिक data को user buffer में copy करना हटाना। इसलिए, stream एक buffer return कर सकता है, जो buffer वास्तव में सीधे उस final data structure की ओर point करता है जिसमें bytes store होंगे, और caller उस buffer से सीधे interact कर सकता है, जिससे बीच की copy operations हट जाती हैं।
उदाहरण के लिए: classic IO stream:
फिर, stream मूल रूप से सिर्फ memcpy() call करके data को pb से user buffer में copy करता है। अगर ZeroCopyInputStream उपयोग करें, तो हमें बस चाहिए:
यहाँ कोई copy नहीं होती, caller अंत में सीधे buffer से पढ़ता है।
ZeroCopyStream दो base classes देता है: ZeroCopyOutputStream/ZeroCopyInputStream।
InputStream का उदाहरण लें, आमतौर पर हम inherit करके अपना ZerCopyStream custom define कर सकते हैं, नीचे के चार interfaces implement करने होंगे।
// implements ZeroCopyInputStream ----------------------------------
bool Next(const void** data, int* size);
void BackUp(int count);
bool Skip(int count);
int64 ByteCount() const;
कुछ rpc frameworks मूल रूप से अपने Stream custom define करते हैं, उदाहरण के लिए: sofa-pbrpc
https://github.com/baidu/sofa-pbrpc/blob/master/src/sofa/pbrpc/buffer.h
2. Demo¶
एक pb protocol define करें, उदाहरण के लिए: authorization verification:
फिर serialization और deserialization लिखें:
- Serialization
BasicAuth auth_message;
auth_message.set_username("user123");
auth_message.set_password("password");
StringOutputStream output_stream(&buf);
auth_message.SerializeToZeroCopyStream(&output_stream);
- Deserialization
ArrayInputStream input_stream(buf.data(), buf.size());
BasicAuth auth_message;
if (!auth_message.ParseFromZeroCopyStream(&input_stream)) {
std::cerr << "Failed to parse data." << std::endl;
}
std::cout << "Username: " << auth_message.username() << std::endl;
std::cout << "Password: " << auth_message.password() << std::endl;
इसके बाद हम इसे call कर सकते हैं:
आउटपुट:
इस section का अंत, ऊपर का पूरा code 知识星球 में देखें, rpc से जुड़ी सामग्री पर मेरे साथ चर्चा करने के लिए स्वागत है।
(gdb) p *dsr
$8 = {typeInfo = {datumlen = 4, typid = 1082, align = 105 'i', byval = true}, datumStreamVersion = DatumStreamVersion_Original, nth = -1,
logical_row_count = 16382, datump = 0x3840470 "\277\377\377\377\231\002", physical_datum_index = -1, physical_datum_count = 0,
datum_beginp = 0x3840470 "\277\377\377\377\231\002", datum_afterp = 0x38503dc "", has_null = true, buffer_beginp = 0x383fc60 "",
null_bitmap = {buffer = 0x383fc70 "", byteBit = 0 '\000', bytePointer = 0x383fc70 "", bitCount = 16382, bitPosition = -1,
readBitOnCount = 58981488}, null_bitmap_beginp = 0x0, rle_can_have_compression = false, rle_compress_beginp = 0x0, rle_repeatcountsp = 0x0,
delta_beginp = 0x0, delta_deltasp = 0x0, delta_datum_p = 0, rle_norepeats_null_bitmap_count = 0, rle_compress_bitmap_count = 0,
rle_repeatcounts_count = 0, rle_repeatcounts_size = 0, delta_item = false, delta_bitmap_count = 0, deltas_count = 0, deltas_size = 0,
rle_block_was_compressed = false, rle_compress_bitmap = {buffer = 0x0, byteBit = 0 '\000', bytePointer = 0x0, bitCount = 0, bitPosition = 0,
readBitOnCount = 0}, rle_repeatcounts_index = 0, rle_in_repeated_item = false, rle_repeated_item_count = 0,
rle_total_repeat_items_read = 0, delta_block_was_compressed = false, delta_bitmap = {buffer = 0x0, byteBit = 0 '\000',
bytePointer = 0xff6c00454244 <error: Cannot access memory at address 0xff6c00454244>, bitCount = 0, bitPosition = 0,
readBitOnCount = 13651600}, eyecatcher = "\000\000\000", physical_data_size = 0, maxDataBlockSize = 13652112,
errdetailCallback = 0x35daeb0, errdetailArg = 0x34c4e18, errcontextCallback = 0x34c4e18, errcontextArg = 0x383fc60, memctxt = 0x1077c}
संबंधित विषय¶
- खुद C++ FnOnce लिखना | C++那些事
- C++ gRPC छोटा project | C++那些事
- C++ inter-process communication व्यवहार | C++那些事
- C++ short URL service Demo | C++那些事
- C++17 और SQLite से directory का size निकालना | C++那些事
- Google Benchmark performance testing | C++那些事
- C++20 coroutine HTTP server | C++那些事
- pybind11 से Python तेज़ करना | C++那些事
- C++ stack calculator design | C++那些事