Boost binary archives - reducing size

mla*_*nca 5 c++ serialization boost archive

I am trying to reduce the memory size of boost archives in C++.

One problem I have found is that Boost's binary archives default to using 4 bytes for any int, regardless of its magnitude. For this reason, I am getting that an empty boost binary archive takes 62 bytes while an empty text archive takes 40 (text representation of an empty text archive: 22 serialization::archive 14 0 0 1 0 0 0 0 0).

Is there any way to change this default behavior for ints?

另外,除了对向量使用 make_array 之外,还有其他方法可以优化二进制存档的大小吗?

seh*_*ehe 3

  1. 问: 我正在尝试减少 C++ 中 boost 存档的内存大小。

    请参阅Boost C++ 序列化开销

  2. 问: 我发现的一个问题是,Boost 的二进制存档默认对任何 int 使用 4 个字节,无论其大小如何。

    那是因为它是序列化库,而不是压缩库

  3. 问: 出于这个原因,我发现一个空的 boost 二进制存档需要 62 个字节,而一个空的文本存档需要 40 个字节(空文本存档的文本表示:22 serialization::archive 14 0 0 1 0 0 0 0 0)。

    使用存档标志:例如来自Boost Serialization:如何预测序列化结果的大小?

    • 调整(boost::archive::no_codecvt、boost::archive::no_header、禁用跟踪等)
  4. 问: 有什么方法可以更改整数的默认行为吗?

    不。不过有BOOST_IS_BITWISE_SERIALIZABLE(T)(请参阅Boost 序列化按位序列化的示例和解释)。

  5. 问:此外,除了用于 向量之外,还有其他方法可以优化二进制存档的大小吗?make_array

    使用make_array对以下情况没有帮助vector<int>

    Live On Coliru

    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/serialization/vector.hpp>
    #include <sstream>
    #include <iostream>
    
    static auto const flags = boost::archive::no_header | boost::archive::no_tracking;
    
    template <typename T>
    std::string direct(T const& v) {
        std::ostringstream oss;
        {
            boost::archive::binary_oarchive oa(oss, flags);
            oa << v;
        }
        return oss.str();
    }
    
    template <typename T>
    std::string as_pod_array(T const& v) {
        std::ostringstream oss;
        {
            boost::archive::binary_oarchive oa(oss, flags);
            oa << v.size() << boost::serialization::make_array(v.data(), v.size());
        }
        return oss.str();
    }
    
    int main() {
        std::vector<int> i(100);
        std::cout << "direct: "       << direct(i).size() << "\n";
        std::cout << "as_pod_array: " << as_pod_array(i).size() << "\n";
    }
    
    Run Code Online (Sandbox Code Playgroud)

    印刷

    direct: 408
    as_pod_array: 408
    
    Run Code Online (Sandbox Code Playgroud)

压缩

最直接的优化方法是压缩结果流(另请参阅此处添加的基准)。

除此之外,您将必须覆盖默认序列化并应用您自己的压缩(可以是简单的游程编码、霍夫曼编码或更特定于域的编码)。

演示

Live On Coliru

#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <sstream>
#include <iostream>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/copy.hpp>

static auto const flags = boost::archive::no_header | boost::archive::no_tracking;

template <typename T>
size_t archive_size(T const& v)
{
    std::stringstream ss;
    {
        boost::archive::binary_oarchive oa(ss, flags);
        oa << v;
    }

    std::vector<char> compressed;
    {
        boost::iostreams::filtering_ostream fos;
        fos.push(boost::iostreams::bzip2_compressor());
        fos.push(boost::iostreams::back_inserter(compressed));

        boost::iostreams::copy(ss, fos);
    }

    return compressed.size();
}

int main() {
    std::vector<int> i(100);
    std::cout << "bzip2: " << archive_size(i) << "\n";
}
Run Code Online (Sandbox Code Playgroud)

印刷

bzip2: 47
Run Code Online (Sandbox Code Playgroud)

压缩率约为 11%(如果删除存档标志,压缩率约为 19%)。