编码的 avro 消息的大小,而不对其进行编码
Size of encoded avro message without encoding it
有没有办法在不实际编码的情况下获取编码的 avro 消息的大小?
我正在使用 Avro 1.8.1 进行C++。
我习惯于谷歌协议缓冲区,您可以在其中调用 protobuf 上的ByteSize()
以获取编码大小,所以这是我正在寻找的类似的东西。
由于消息本质上是一个原始结构,因此我得到无法从消息本身检索大小,但也许有一个我不知道的辅助方法?
(下面的编辑显示了一种在用BinaryEncoder
写入OutputStream
后缩小以适应它的黑客方法)
遗憾的是,avro::encode()
没有在编码后OutputStream
上使用backup
来释放未使用的内存。Martin G 的回答仅使用 avro 提供的工具给出了最佳解决方案,但如果序列化对象的大小为 N 个字节,它会发出 N 个内存分配,每个内存分配 1 个字节。
您可以实现一个自定义avro::OutputStream
,该仅计算和丢弃所有写入的字节。这将摆脱内存分配。这仍然不是一个很好的方法,因为实际的编码器必须"询问"每个字节:
(代码未经测试,仅用于演示目的)
#include <avro/Encoder.hh>
#include <cstdint>
class ByteCountOutputStream : public avro::OutputStream {
public:
size_t byteCount_ = 0;
uint8_t dummyWriteLocation_;
explicit ByteCountOutputStream() {};
bool next(uint8_t **data, size_t *len) final {
byteCount_ += 1;
*data = &dummyWriteLocation_;
*len = 1;
return true;
}
void backup(size_t len) final {
byteCount_ -= len;
}
uint64_t byteCount() const final {
return byteCount_;
}
void flush() final {}
};
然后可以将其用作:
MyAvroStruct obj;
avro::EncoderPtr encoder = avro::binaryEncoder();
ByteCountOutputStream out();
encoder->init(out);
avro::encode(*encoder, obj);
size_t bufferSize = out.byteCount();
<小时 />编辑: 偶然发现这一点时,我的第一个问题是:我如何知道需要多少字节的OutputStream
(用于存储/传输)?或者,等效地,如果OutputStream.byteCount()
返回编码器到目前为止分配的字节数,如何使编码器"备份"/释放它不使用的字节数?好吧,有一个黑客方法:
Encoder
抽象类提供了一个init
方法。对于 BinaryEncoder,这目前实现为:
void BinaryEncoder::init(OutputStream &os) {
out_.reset(os);
}
out_
是编码器的内部StreamWriter
。
现在,StreamWriter
实现reset
为:
void reset(OutputStream &os) {
if (out_ != nullptr && end_ != next_) {
out_->backup(end_ - next_);
}
out_ = &os;
next_ = end_;
}
这会在切换到新内存之前将未使用的内存返回到"旧"输出流。
因此,您可以像这样滥用编码器的 init 方法:
// setup as always
MyAvroStruct obj;
avro::EncoderPtr encoder = avro::binaryEncoder();
std::auto_ptr<avro::OutputStream> out = avro::memoryOutputStream();
// actual serialization
encoder->init(*out);
avro::encode(*encoder, obj);
// re-init on the same OutputStream. Happens to shrink the stream to fit
encoder->init(*out);
size_t bufferSize = out->byteCount();
但是,此行为未记录在案,因此将来可能会中断。
不幸的是,没有办法绕过它...
下面是一个示例,显示了如何通过对对象进行编码来计算大小:
MyAvroStruct obj;
avro::EncoderPtr encoder = avro::binaryEncoder();
std::auto_ptr<avro::OutputStream> out = avro::memoryOutputStream(1);
encoder->init(*out);
avro::encode(*encoder, obj);
out->flush();
uint32_t bufferSize = out->byteCount();
- 如何确定我已使用非编码文件到达 EOF?
- 使用 MATLAB 编码器生成C++代码:编译错误"undefined reference to `rgb2gray_tbb_real64'"
- 在卡萨布兰卡形成编码参数的列表
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 使用C++进行游程编码
- 如何将不同的可执行文件合并到一个窗口框架中进行编码?像浏览器一样
- 使用已使用 java 编码的 openssl 解码数据
- boost 是否有按特殊类型值编码状态"compact optional"?
- 如何在CPP的给定目录中列出UTF编码的文件名?
- 如何使用 C++将 ISO-2022-KR 编码转换为 UTF-8 编码?
- 绝对编码器十六进制输入
- 防止C++中的硬编码数字
- 将C++ std::string 转换为 UTF-16-LE 编码的字符串
- 使用文件内容作为硬编码字符串
- 运行长度编码程序 c++ 的问题
- 以C++为单位进行运行长度编码
- *新的编码器*格式和运算符
- 在CRC-16 CCITT中将数据从二进制解码为文本,我应该输入一个码字,使用CRC生成器进行编码
- 使用 IMFSinkWriter 编码的视频的播放速度会根据宽度而变化
- 编码的 avro 消息的大小,而不对其进行编码