【问题标题】:Boost binary archives - reducing size提升二进制档案 - 减小大小
【发布时间】:2018-01-30 03:25:04
【问题描述】:

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

我发现的一个问题是 Boost 的二进制存档默认为任何 int 使用 4 个字节,无论其大小如何。出于这个原因,我知道一个空的 boost 二进制存档需要 62 个字节,而一个空的文本存档需要 40 个字节(空文本存档的文本表示:22 serialization::archive 14 0 0 1 0 0 0 0 0)。

有什么方法可以改变整数的这种默认行为吗?

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

【问题讨论】:

    标签: c++ serialization boost archive


    【解决方案1】:
    1. 问。 我正在尝试减少 C++ 中 boost 存档的内存大小。

      Boost C++ Serialization overhead

    2. Q. 我发现的一个问题是 Boost 的二进制存档默认为任何 int 使用 4 个字节,而不管它的大小。

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

    3. Q. 出于这个原因,我知道一个空的 boost 二进制存档需要 62 个字节,而一个空的文本存档需要 40 个字节(空文本存档的文本表示:22 序列化: :存档 14 0 0 1 0 0 0 0 0)。

      使用存档标志:例如来自Boost Serialization : How To Predict The Size Of The Serialized Result?

      • 调整内容(boost::archive::no_codecvt、boost::archive::no_header、disable tracking 等)
    4. 问。 有什么方法可以改变整数的这种默认行为吗?

      没有。不过有BOOST_IS_BITWISE_SERIALIZABLE(T)(参见例如Boost serialization bitwise serializability 的示例和解释)。

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

      使用make_arrayvector<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";
      }
      

      打印

      direct: 408
      as_pod_array: 408
      

    压缩

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

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

    演示

    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";
    }
    

    打印

    bzip2: 47
    

    这是一个约 11% 的压缩率(如果您放弃存档标志,则为约 19%)。

    【讨论】:

      【解决方案2】:

      正如 Alexey 所说,在 Boost 中,您必须使用较小的成员变量。唯一做得更好的序列化是 AFAIK、Google Protocol Buffers 和 ASN.1 PER。

      GPB 使用可变长度整数来使用适合传输值的字节数。

      ASN.1 PER 以不同的方式处理它;在 ASN.1 方案中,您可以定义值的有效范围。因此,如果您声明一个 int 字段具有 0 到 15 之间的有效范围,它将仅使用 4 位。 uPER 更进一步;它不会将字段的位与字节边界对齐,从而节省更多位。 uPER 是 3G、4G 在无线链路上使用的,节省了大量带宽。

      据我所知,大多数其他努力都涉及使用 ZIP 或类似的后序列化压缩。对大量数据很好,否则就是垃圾。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-01-02
        • 2014-11-18
        • 2011-10-09
        • 1970-01-01
        • 1970-01-01
        • 2014-08-07
        • 1970-01-01
        相关资源
        最近更新 更多