c++ - Boost:重新使用/清除 text_iarchive 以反序列化来自 Asio:receive() 的数据

标签 c++ serialization boost deserialization boost-asio

这是我当前的函数,它对通过 Boost:Asio UDP 传输接收的数据进行反序列化。它工作得很好,但是性能很差。每秒大约 4000 次左右的调用将使用 ~16% 的 CPU,这是 I7 的一个完整线程。

对代码运行性能测试表明该行使用了 >95% 的 cpu 时间:

text_iarchive LLArchive(LLStream);

我的问题很简单:有没有一种方法可以重复使用 text_iarchive 而不必在每次调用该函数时都创建一个新文件? (在 C# 中,使用内存流和反序列化数据所需的其他变量可能会发生类似的事情)。我搜索了 Boost 文档,但没有提到类似的内容。

我本质上想要的是将下面的函数放在一个类中,并将尽可能多的变量定义为成员,这些成员将通过重新初始化(清除缓冲区/流、重新设置数据等)简单地在函数内部使用.这甚至会 boost 性能吗?更改传递到存档中的流是否足以达到目的(它是否将其绑定(bind)到某处,以便如果我们更改传递的流,存档设置为自身的流也会更改)?

这可能吗?

非常感谢您的宝贵时间!

完整功能代码:

using namespace boost::archive;
using namespace boost::iostreams;

Packet InboundStreamToInternalPacket(boost::array<char, 5000> inboundStream)
{
    Packet receivedPacket; 

    basic_array_source<char> arraySourceLL(inboundStream.data(), inboundStream.size());
    stream<basic_array_source<char>> LLStream(arraySourceLL);
    text_iarchive LLArchive(LLStream);

    LLArchive >> receivedPacket;

    return receivedPacket;
}

编辑 1:

尝试关闭并再次打开流,就好像添加了新源一样,在反序列化到第二个数据包时崩溃并出现“boost::archive::archive_exception at memory location xxxxxx”。

Packet InboundStreamToInternalPacket(boost::array<char, 5000> inboundStream)
{
    Packet receivedPacket; 
    Packet receivedPacket2;

    basic_array_source<char> arraySourceLL(inboundStream.data(), inboundStream.size());
    stream<basic_array_source<char>> LLStream;     
    LLStream.open(arraySourceLL);

    text_iarchive LLArchive(LLStream);    

    LLArchive >> receivedPacket;

    LLStream.close();

    LLStream.open(arraySourceLL);

    LLArchive >> receivedPacket2;

    return receivedPacket;
}

最佳答案

不,没有这样的方法。

虽然与 MemoryStream 的比较是错误的,因为存档是流之上的层。

可以重复使用流。因此,如果您执行与 MemoryStream 完全平行的操作,例如boost::iostreams::array_sink 和/或 boost::iostreams::array_source 在固定缓冲区上,您可以轻松地在下一个(反)序列化中重用缓冲区。

查看此概念证明:

Live On Coliru

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/serialization.hpp>

#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <sstream>

namespace bar = boost::archive;
namespace bio = boost::iostreams;

struct Packet {
    int i;
    template <typename Ar> void serialize(Ar& ar, unsigned) { ar & i; }
};

namespace Reader {
    template <typename T>
    Packet deserialize(T const* data, size_t size) {
        static_assert(boost::is_pod<T>::value     , "T must be POD");
        static_assert(boost::is_integral<T>::value, "T must be integral");
        static_assert(sizeof(T) == sizeof(char)   , "T must be byte-sized");

        bio::stream<bio::array_source> stream(bio::array_source(data, size));
        bar::text_iarchive ia(stream);
        Packet result;
        ia >> result;

        return result;
    }

    template <typename T, size_t N>
    Packet deserialize(T (&arr)[N]) {
        return deserialize(arr, N);
    }

    template <typename T>
    Packet deserialize(std::vector<T> const& v) {
        return deserialize(v.data(), v.size());
    }

    template <typename T, size_t N>
    Packet deserialize(boost::array<T, N> const& a) {
        return deserialize(a.data(), a.size());
    }
}

template <typename MutableBuffer>
void serialize(Packet const& data, MutableBuffer& buf)
{
    bio::stream<bio::array_sink> s(buf.data(), buf.size());
    bar::text_oarchive ar(s);

    ar << data;
}

int main() {
    boost::array<char, 1024> arr;

    for (int i = 0; i < 100; ++i) {
        serialize(Packet { i }, arr);

        Packet roundtrip = Reader::deserialize(arr);
        assert(roundtrip.i == i);
    }
    std::cout << "Done\n";
}

对于 boost 序列化的一般优化,请参阅:

关于c++ - Boost:重新使用/清除 text_iarchive 以反序列化来自 Asio:receive() 的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28395531/

相关文章:

c# - IXmlSerialized 根据架构进行验证

c++ - boost spirit x3 : parse into structs

c++ - glClearBufferData - 使用示例?

python - 如何从 JSON 获取字符串对象而不是 Unicode

c++ - 如何在 C++ 中交叉包含类?

c++ - 当我将它放在 while 语句之外时,为什么我的 ofstream 不起作用?

c++ - BJAM,为 vc-80 而不是 vc7.1 构建

c++ - Cmake 找不到 Boost 库

c++ - 如何在 C++11 标准中初始化一个动态大小的数组?

c++ - 模板的模板成员的消歧模板关键字 : when exactly?