【问题标题】:Boost C++ Serialization overhead提高 C++ 序列化开销
【发布时间】:2014-04-22 23:23:30
【问题描述】:

我正在尝试使用以下代码测量序列化开销

    const int message_size=1000;

    std::vector<short> message(message_size);

    std::string s((char*)(&message[0]), message_size * sizeof(short));

    double size= 1000*sizeof(short);
    double size2= s.size();
    double overhead = size2 - size; //is zero

正确吗? (取自 vector serialization)

如何衡量序列化开销? - 主要问题是测量序列化向量。 我可以使用 Boost 进行序列化。

【问题讨论】:

  • 这和Boost.Serialization有什么关系?
  • 我可以(甚至应该)使用 boost 库进行序列化。
  • 重点是你的问题毫无意义。不涉及序列化,当然overhead 为0,因为您刚刚创建了长度为1000*sizeof(short)s。为什么您希望它的大小与您要求的不同?投射不是序列化。
  • 你的意思是boost文本序列化比二进制序列化的内存开销吗?否则我也不明白。二进制存档应该没有内存开销,因为它是实际数据。
  • @OlegAndriyanov 当然有开销,因为它也有元数据。

标签: c++ serialization boost


【解决方案1】:

这个通用测试平台应该能让你做出决定:看看它Live On Coliru

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>
#include <boost/make_shared.hpp>
#include <boost/phoenix.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/tuple/tuple.hpp>
#include <iostream>
#include <sstream>

namespace detail
{
    struct add_to_archive_f 
    {
        template <typename, typename> struct result { typedef void type; };
        template <typename Archive, typename T> 
            void operator()(Archive& ar, T const& t) const {
                ar << BOOST_SERIALIZATION_NVP(t);
            }
    };

    static const boost::phoenix::function<add_to_archive_f> add_to_archive { };
}

template <typename Archive = boost::archive::binary_oarchive, typename... Data>
size_t archive_size(Data const&... data)
{
    std::ostringstream oss;
    Archive oa(oss);

    boost::fusion::for_each(boost::make_tuple(data...), 
            detail::add_to_archive(
                boost::phoenix::ref(oa), 
                boost::phoenix::arg_names::arg1
                ));

    return oss.str().size();
}

template <typename Archive = boost::archive::binary_oarchive, typename... Data>
void benchmark(Data const&... data)
{
    std::cout << __PRETTY_FUNCTION__ << ":\t" << archive_size<Archive>(data...) << "\n";
}

struct Base {
    boost::array<double, 1000> data;
    virtual ~Base() {}

  private:
    friend class boost::serialization::access;
    template <typename Archive> void serialize(Archive& ar, unsigned /*version*/) {
        ar & BOOST_SERIALIZATION_NVP(data);
    }
};

struct Derived : Base {
    std::string x;
    Derived() : x(1000, '\0') { }

  private:
    friend class boost::serialization::access;
    template <typename Archive> void serialize(Archive& ar, unsigned /*version*/) {
        ar & boost::serialization::make_nvp("base", boost::serialization::base_object<Base>(*this));
        ar & BOOST_SERIALIZATION_NVP(x);
    }
};

测试驱动:

template <typename Archive> 
void some_scenarios()
{
    benchmark<Archive>(std::vector<char>(1000));
    benchmark<Archive>(boost::make_shared<std::vector<char>>(1000));
    benchmark<Archive>(3.14f, 42, 42ull, "hello world");
    benchmark<Archive>(boost::make_shared<Base>());
    benchmark<Archive>(boost::make_shared<Derived>());
}

int main()
{
    some_scenarios<boost::archive::binary_oarchive>();
    some_scenarios<boost::archive::text_oarchive>();
    some_scenarios<boost::archive::xml_oarchive>();
}

在我的 64 位 Ubuntu 上使用 Boost 1.55 的输出:

void benchmark(const Data& ...) [with Archive = boost::archive::binary_oarchive; Data = {std::vector<char, std::allocator<char> >}]:    1052
void benchmark(const Data& ...) [with Archive = boost::archive::binary_oarchive; Data = {boost::shared_ptr<std::vector<char, std::allocator<char> > >}]:    1059
void benchmark(const Data& ...) [with Archive = boost::archive::binary_oarchive; Data = {float, int, long long unsigned int, char [12]}]:   76
void benchmark(const Data& ...) [with Archive = boost::archive::binary_oarchive; Data = {boost::shared_ptr<Base>}]: 8069
void benchmark(const Data& ...) [with Archive = boost::archive::binary_oarchive; Data = {boost::shared_ptr<Derived>}]:  9086
void benchmark(const Data& ...) [with Archive = boost::archive::text_oarchive; Data = {std::vector<char, std::allocator<char> >}]:  2037
void benchmark(const Data& ...) [with Archive = boost::archive::text_oarchive; Data = {boost::shared_ptr<std::vector<char, std::allocator<char> > >}]:  2043
void benchmark(const Data& ...) [with Archive = boost::archive::text_oarchive; Data = {float, int, long long unsigned int, char [12]}]: 92
void benchmark(const Data& ...) [with Archive = boost::archive::text_oarchive; Data = {boost::shared_ptr<Base>}]:   2049
void benchmark(const Data& ...) [with Archive = boost::archive::text_oarchive; Data = {boost::shared_ptr<Derived>}]:    3083
void benchmark(const Data& ...) [with Archive = boost::archive::xml_oarchive; Data = {std::vector<char, std::allocator<char> >}]:   16235
void benchmark(const Data& ...) [with Archive = boost::archive::xml_oarchive; Data = {boost::shared_ptr<std::vector<char, std::allocator<char> > >}]:   17307
void benchmark(const Data& ...) [with Archive = boost::archive::xml_oarchive; Data = {float, int, long long unsigned int, char [12]}]:  436
void benchmark(const Data& ...) [with Archive = boost::archive::xml_oarchive; Data = {boost::shared_ptr<Base>}]:    19393
void benchmark(const Data& ...) [with Archive = boost::archive::xml_oarchive; Data = {boost::shared_ptr<Derived>}]: 21508

如你所见,

  • XML 的开销很大
  • 对于二进制文件,对于许多不同(例如多态)小类型元素的小型档案,开销会变得很大

【讨论】:

  • 使用 bzip2 压缩添加测量值:Live On Coliru(我已随机化数据以使数据本身不可压缩)(有趣的是,“小”数据集是压缩文本存档比压缩二进制存档更有效。所有其他情况都与预期的差不多)
猜你喜欢
  • 1970-01-01
  • 2011-11-01
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 2011-12-27
  • 2020-05-20
  • 1970-01-01
  • 2023-04-10
相关资源
最近更新 更多