如何优化C++ Randomclass序列化中vector的数据追加效率?
C++序列化中vector追加操作的优化方案
你的序列化代码里用insert向std::vector<uint8_t>追加数据,确实有不少优化空间,下面是几个实用的优化方向:
1. 预分配内存,减少vector扩容开销
std::vector默认扩容策略是每次翻倍,频繁扩容会触发内存重新分配和数据拷贝。提前计算好所需总字节数并调用reserve(),能一次性分配足够空间,避免这些额外开销。
计算总字节数时需要考虑:
- 字符串/容器长度的LEB128编码最大长度(
uint32_t最多需要5字节) - 字符串/容器本身的字节数
示例代码:
std::vector<uint8_t> Buf; const size_t nameLen = Ramdom.getName().length(); const size_t contentLen = Ramdom.getContent().size(); // 预分配:name的LEB128编码(最多5字节) + name长度 + content的LEB128编码(最多5字节) + content大小 Buf.reserve(5 + nameLen + 5 + contentLen);
2. 直接写入数据,避免临时vector
当前EncodeU32返回临时vector,再通过insert拷贝到目标容器,多了一次内存分配和拷贝。可以修改EncodeU32,直接把编码后的字节写入目标vector:
void EncodeU32(uint32_t d, std::vector<uint8_t>& out) { // unsigned LEB128 encoding do { auto x = d & 0b01111111; d >>= 7; if (d) x |= 0b10000000; out.push_back(x); // 直接写入目标容器,无临时对象 } while (d); }
调用时直接传入目标vector即可,无需临时变量:
EncodeU32(Ramdom.getName().length(), Buf);
3. 用append替代insert追加字节序列
对于字符串或连续字节序列,vector::append()比insert(Buf.end(), begin, end)更贴合场景,部分标准库实现会对append做针对性优化,代码也更简洁:
// 追加name内容 Buf.append(Ramdom.getName().data(), Ramdom.getName().size()); // 追加content内容 Buf.append(Ramdom.getContent().data(), Ramdom.getContent().size());
优化后的完整代码示例
void EncodeU32(uint32_t d, std::vector<uint8_t>& out) { do { auto x = d & 0b01111111; d >>= 7; if (d) x |= 0b10000000; out.push_back(x); } while (d); } std::vector<uint8_t> Serialize(Ramdomclass &Ramdom) { std::vector<uint8_t> Buf; const size_t nameLen = Ramdom.getName().length(); const size_t contentLen = Ramdom.getContent().size(); Buf.reserve(5 + nameLen + 5 + contentLen); // 序列化name EncodeU32(nameLen, Buf); Buf.append(Ramdom.getName().data(), nameLen); // 序列化content EncodeU32(contentLen, Buf); Buf.append(Ramdom.getContent().data(), contentLen); // 组装最终结果 std::vector<uint8_t> Result; Result.reserve(1 + 5 + Buf.size()); // 1字节版本号 + 最多5字节Buf长度 + Buf实际长度 Result.push_back(0x00U); EncodeU32(Buf.size(), Result); // 用移动迭代器避免最后一次拷贝(Buf后续不再使用) Result.insert(Result.end(), std::make_move_iterator(Buf.begin()), std::make_move_iterator(Buf.end())); return Result; }
额外优化点
如果getContent()返回的是std::vector<uint8_t>,可以用std::move转移数据到Result,避免冗余拷贝,就像上面代码里的std::make_move_iterator用法一样。
内容的提问来源于stack exchange,提问作者Sebastian Orteho
相关产品推荐
相关产品推荐

