提升序列化:如何预测序列化结果的大小?

时间:2015-05-27 22:53:44

标签: c++ serialization boost structure

我以这种方式使用booost序列化:

Header H(__Magic, SSP_T_REQUEST, 98, 72, 42, Date(), SSP_C_NONE);
Header Z;

std::cout << H << std::endl;
std::cout << std::endl;

char serial_str[4096];

std::memset(serial_str, 0, 4096);

boost::iostreams::basic_array_sink<char> inserter(serial_str, 4096);
boost::iostreams::stream<boost::iostreams::basic_array_sink<char> > s(inserter);
boost::archive::binary_oarchive oa(s);

oa & H;
s.flush();

std::cout << serial_str << std::endl;

boost::iostreams::basic_array_source<char> device(serial_str, 4096);
boost::iostreams::stream<boost::iostreams::basic_array_source<char> > s2(device);
boost::archive::binary_iarchive ia(s2);

ia >> Z;

std::cout << Z << std::endl;

它完美无缺。

然而,我需要在套接字上发送这些数据包。我的问题是,我怎么知道在另一边需要读多少字节?序列化结果的大小不是常数,btw大于我的struct的sizeof。

如何确保数据在另一方面完整?我使用循环缓冲区,但序列化怎么办?

全部

2 个答案:

答案 0 :(得分:1)

一般来说,无法预测。它(很多)取决于存档格式。但是通过对象跟踪,可以省略子图,并且通过动态类型信息可以添加大量数据。

如果您可以为序列化数据提供暂存缓冲区,则可以先将序列化为缓冲区,然后在发送有效负载之前发送大小(现在就知道了)。

会有开销
  • 对象跟踪(通过指针/引用进行序列化)
  • 动态多态(通过(智能)指针到基础的序列化)
  • 版本控制(除非您为所涉及的类型禁用它)
  • 归档标题(除非已禁用)
  • 代码转换(除非禁用)

以下是一些答案,为您提供有关这些调整点的更多信息:

如果您的所有数据都是POD,则很容易预测大小。

开箱即用

如果您在同一台机器上共享IPC,并且您已经在使用循环缓冲区,请考虑将循环缓冲区放入共享内存中。

我有很多答案(搜索managed_shared_memorymanaged_mapped_file)并举例说明。

一个具体的例子,关注一个无锁的单一生产者/单一消费者场景:Shared-memory IPC synchronization (lock-free)

即使您选择/需要流式传输消息(例如通过网络),您仍然可以使用例如Managed External Buffers。因此,即使不要求所有数据都是POD,您也可以避免执行任何序列化。 (诀窍在于内部,使用offset_ptr<>而不是原始指针,使所有引用相对)。

答案 1 :(得分:-1)

创建自己的流式类并覆盖xsputn方法。

class counter_streambuf : public std::streambuf {
public:
    using std::streambuf::streambuf;

    size_t size() const { return m_size; }

protected:
    std::streamsize xsputn(const char_type* __s, std::streamsize __n) override 
    { this->m_size += __n; return __n; }

private:
    size_t m_size = 0;
};

用法:

Header H(__Magic, SSP_T_REQUEST, 98, 72, 42, Date(), SSP_C_NONE);
counter_streambuf csb;
boost::archive::binary_oarchive oa(csb, boost::archive::no_header);
oa & H;
cout<<"Size: "<<csb.size();