繁体   English   中英

Boost:重复使用/清除text_iarchive以便从Asio:receive()反序列化数据

[英]Boost: Re-using/clearing text_iarchive for de-serializing data from Asio:receive()

这是我当前的功能,可以反序列化通过Boost:Asio UDP传输接收的数据。 它可以完美运行, 但是性能却很差。 每秒大约4000次调用将占用约16%的CPU,这是I7的全线程。

对代码运行性能测试表明,此行使用了超过95%的cpu时间:

text_iarchive LLArchive(LLStream);

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

我本质上想要的是将函数放在一个类中,并具有尽可能多的变量定义为成员,这些成员可以通过重新初始化(清除缓冲区/流,重新设置数据等)在函数内部简单使用。 这会提高性能吗? 更改传递到存档中的流是否足以解决问题(将它绑定到某个地方,以便如果我们更改传递的流,则存档本身设置的流也会发生变化)吗?

可能吗?

非常感谢您的宝贵时间!

全功能代码:

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:

尝试重新关闭和打开流,就像添加了新的源一样,在反序列化到第二个Packet时,崩溃并显示为“ boost :: archive :: archive_exception在内存位置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 ,则可以在下一个(反)序列化中轻松地重用该缓冲区。

请参阅此概念证明:

生活在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序列化的一般优化,请参见:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM