提高序列化按位序列化能力

Bik*_*eev 5 c++ serialization boost

我期望从 is_bitwise_serialized 特性中序列化类,如下所示(没有序列化函数):

class A { int a; char b; };
BOOST_IS_BITWISE_SERIALIZABLE(A);
A a{2, 'x'};
some_archive << a; // serializes a bitwisely
Run Code Online (Sandbox Code Playgroud)

我想知道,为什么需要为bitwise_serialized类提供序列化函数?

seh*_*ehe 5

从文档中:

一些简单的类只需直接复制类的所有位即可序列化。对于不包含指针成员且既不进行版本控制也不进行跟踪的 POD 数据类型来说尤其如此。某些档案(例如不可移植的二进制档案)可以利用此信息来显着加快序列化速度。

为了指示按位序列化的可能性,使用头文件 is_bitwise_serialized.hpp 中定义的类型特征:

重点来了:本次优化

  • 在适用的存档类型中是可选的

  • 不适用于所有存档类型,例如

    • 需要可移植的二进制存档无法通过复制原始内存表示来实现(因为它依赖于实现和平台)

    • 文本存档可能不希望对此进行优化(例如,它有不同的目标,例如“人类可读的 XML”,他们可能不想将您的代码编码vector<A>为大型 bas64 编码的 blob)。

请注意,这也解释了它is_bit_wise_serializable<T>并不部分专门用于具有以下功能的任何类型is_pod<T>::value == true(这在技术上可以轻松完成):

  • 有些类可能对序列化它们的所有状态不感兴趣(因此使用按位复制会比仅仅选择感兴趣的位占用更多的空间(双关语))

您没有具体询问,但这就是工作实现的样子:

#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <sstream>

struct A { int a; char b;
    template <typename Ar> void serialize(Ar& ar, unsigned) {
        ar & a;
        ar & b;
    }
};

BOOST_IS_BITWISE_SERIALIZABLE(A)

int main() {
    std::ostringstream oss;
    boost::archive::binary_oarchive oa(oss);

    A data { 1, 'z' };
    oa << data;
}
Run Code Online (Sandbox Code Playgroud)

更新

为了回应基本上再次提出相同问题的评论者,我提出了一个演示,当按位序列化会(a)产生明显的差异(b)不会导致较小的存档时:

住在科里鲁

#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/serialization.hpp>

#include <array>
#include <fmt/ranges.h>
#include <span>
#include <sstream>

struct A {
    int  a;
    char b;
    void serialize(auto& ar, unsigned) { ar& a& b; }
};

#ifdef BITWISE
BOOST_IS_BITWISE_SERIALIZABLE(A)
#endif

int main() {
    std::ostringstream oss;
    {
        boost::archive::binary_oarchive oa(oss,
                boost::archive::no_header |
                boost::archive::no_tracking |
                boost::archive::no_codecvt);

        std::array<A, 26> data{{
            {1, 'z'},  {2, 'y'},  {3, 'x'},  {4, 'w'},  {5, 'v'},  {6, 'u'},  {7, 't'},
            {8, 's'},  {9, 'r'},  {10, 'q'}, {11, 'p'}, {12, 'o'}, {13, 'n'}, {14, 'm'},
            {15, 'l'}, {16, 'k'}, {17, 'j'}, {18, 'i'}, {19, 'h'}, {20, 'g'}, {21, 'f'},
            {22, 'e'}, {23, 'd'}, {24, 'c'}, {25, 'b'}, {26, 'a'},
        }};

        oa << data;
    }

    auto raw = oss.str();
    fmt::print("raw serialized form {} bytes: {::#04x}\n", //
               raw.size(), std::vector(raw.begin(), raw.end()));
}
Run Code Online (Sandbox Code Playgroud)

构建运行时:

for def in REGULAR BITWISE; do g++ -std=c++20 -O2 -Wall -pedantic main.cpp -lboost_serialization -lfmt -o $def -D$def & done; wait
set -x; ./REGULAR; ./BITWISE
Run Code Online (Sandbox Code Playgroud)

印刷

+ ./REGULAR
raw serialized form 148 bytes: [0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7a, 0x02, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00, 0x00, 0x00, 0x77, 0x05, 0x00, 0x00, 0x00, 0x76, 0x06, 0x00, 0x00, 0x00, 0x75, 0x07, 0x00, 0x00, 0x00, 0x74, 0x08, 0x00, 0x00, 0x00, 0x73, 0x09, 0x00, 0x00, 0x00, 0x72, 0x0a, 0x00, 0x00, 0x00, 0x71, 0x0b, 0x00, 0x00, 0x00, 0x70, 0x0c, 0x00, 0x00, 0x00, 0x6f, 0x0d, 0x00, 0x00, 0x00, 0x6e, 0x0e, 0x00, 0x00, 0x00, 0x6d, 0x0f, 0x00, 0x00, 0x00, 0x6c, 0x10, 0x00, 0x00, 0x00, 0x6b, 0x11, 0x00, 0x00, 0x00, 0x6a, 0x12, 0x00, 0x00, 0x00, 0x69, 0x13, 0x00, 0x00, 0x00, 0x68, 0x14, 0x00, 0x00, 0x00, 0x67, 0x15, 0x00, 0x00, 0x00, 0x66, 0x16, 0x00, 0x00, 0x00, 0x65, 0x17, 0x00, 0x00, 0x00, 0x64, 0x18, 0x00, 0x00, 0x00, 0x63, 0x19, 0x00, 0x00, 0x00, 0x62, 0x1a, 0x00, 0x00, 0x00, 0x61]
+ ./BITWISE
raw serialized form 221 bytes: [0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x77, 0x7f, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x76, 0x7f, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x7f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x74, 0x7f, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x73, 0x7f, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x72, 0x7f, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x71, 0x7f, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x6c, 0x7f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x69, 0x7f, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x66, 0x7f, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x65, 0x7f, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x64, 0x7f, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x63, 0x7f, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00]
Run Code Online (Sandbox Code Playgroud)