我有一个嵌入式C ++项目,我从硬件设备读取一系列int32,然后将它们作为大数据结构的一部分打包到int数组中,然后发送到远程系统通过TCP / IP。因此,我使用了一个简单的数据结构,并定义了一堆东西,现在我想将其转换为使用Protocol Buffers。 所以,我正在考虑使用"重复的int32数据"作为我的原型buff的元素。但我想避免使用这样的循环:
int hardware_data[1000]; // An array that holds the data read from the hardware
for(int i=0; i< sizeof(hardware_data); i++ )
{
proto.add_data( hardware_data[i] );
}
我更倾向于使用一种有效的方法,例如使proto buff只指向现有的hardware_data []数组(零拷贝方法),或者使用memcpy从hardware_data指向proto.data。
我理解如何设置memcpy(),但是proto buff如何知道proto.data&#34;数组中有多少元素?#34;? 我还可以使用proto.data_size()来获取元素的数量吗? 有没有一种有效的方法将数据从我的硬件读取移动到proto buff进行发送? 有更好的方法吗?
Kerrik, 我不知道零拷贝API。这是我的原型定义:
message hardware_data
{
optional Lob lob = 1;
optional int32 taskSeqNum = 2;
optional int32 secondsOfDay = 3;
optional float IQOutRateKhz = 4;
optional float IQBwKhz = 5;
optional int32 tStart = 6;
optional int32 tOffset = 7;
optional float collectionTime = 8;
optional int32 numSamples = 9;
optional int32 chunk = 10;
optional int32 dimSize = 11;
repeated int32 data = 12 [packed=true];
}
我不确定零拷贝如何在这个原型buff定义中发挥作用。
答案 0 :(得分:1)
在线上,打包重复的int32被编码为一系列varints。 varint是一种可变宽度编码,其中较小的值占用较少的空间。当然,这不是数据在数组中的表示方式,因此实际上不可能将其嵌入到消息零拷贝中。
事实上,你现在正在做两份副本,你可以删除其中一本。不要直接分配int hardware_data[1000]
,而应考虑将数据直接粘贴到google::protobuf::RepeatedField<int>
中。然后,您可以巧妙地使用Swap()
将该数据移动到没有副本的消息中:
RepeatedField<int> hardware_data;
hardware_data.Reserve(expected_size);
get_data_somehow(&hardware_data);
// later
proto.mutable_data()->Swap(&hardware_data);
在序列化消息之后,您可能希望另外交换()字段,以便您可以重用已保留的内存。 (RepeatedField::Clear()
不会释放底层内存,只需将其标记为可重用。)
尽管如此,序列化消息仍然需要复制数据作为编码的一部分。即使您将编码更改为打包重复的fixed32(实际上在线上编码为32位整数),也无法说服库直接使用您的内存。