Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可以重用二进制软件实例?_C++_Performance_Boost_Boost Serialization - Fatal编程技术网

C++ 是否可以重用二进制软件实例?

C++ 是否可以重用二进制软件实例?,c++,performance,boost,boost-serialization,C++,Performance,Boost,Boost Serialization,我的问题与五年前讨论的相同(没有很好的答案) 我将对象序列化到字节缓冲区中,如下所示: std::string serial_str; for (i = 1; i < 10000; i++) { boost::iostreams::back_insert_device<std::string> inserter(serial_str); boost::iostreams::stream<boost::iostreams::back_insert_devic

我的问题与五年前讨论的相同(没有很好的答案)

我将对象序列化到字节缓冲区中,如下所示:

std::string serial_str;
for (i = 1; i < 10000; i++)
{
    boost::iostreams::back_insert_device<std::string> inserter(serial_str);
    boost::iostreams::stream<boost::iostreams::back_insert_device<std::string> > s(inserter);
    boost::archive::binary_oarchive oa(s);

    oa << obj;

    s.flush();

    // code to send serial_str's content to another process, omitted.

    serial_str.clear(); // clear the buffer so it can be reused to serialize the next object
}    
std::string serial\u str;
对于(i=1;i<10000;i++)
{
boost::iostreams::back\u insert\u设备插入器(串行\u str);
boost::iostreams::流s(插入器);
boost::archive::binary_oarchive oa(s);

oa一种解决方案,无需进一步查看,就是存储字符串的最后一个长度,并使用最后一个长度和实际长度(将是添加到输出中的最后一个字符串)获取子字符串。每10或100次迭代,您就可以重新启动
二进制\u oarchive
,而不必在
串行\u str

中积累太多过去的编码对象。是的,从某种意义上说,您完全可以重用它。oarchive只是打包一个流,而不知道流的数据发生了什么,所以诀窍是实现您自己的流(这并不有趣)允许您“重置”实际的基线数据流。我以前写过类似的东西,它工作得非常好

不过,有些问题需要注意:

oarchive不会一直写出标题信息(因为如果它持续存在,它会将所有内容都视为一个大流),因此您需要禁用标题:

boost::archive::binary_oarchive oa(s, boost::archive::no_codecvt | boost::archive::no_header);
另外,因为您要重用oarchive,所以在管理其内部类型表时必须非常小心。如果您序列化的都是int、float等,那么您就没事了,但一旦开始序列化类、字符串等,就不能依赖于存档在重用存档时使用的默认类型枚举就像这样。Boost文档并没有真正涉及到这一点,但对于任何复杂的内容,您都需要对归档遇到的每种类型执行以下操作:

oa.template register_type<std::string>();
oa.template register_type<MyClass>();
oa.template register_type<std::shared_ptr<MyClass> >();
oa.template register_type();
oa.template register_type();
oa.template register_type();
以此类推。对于所有类型,所有的std::vectors,所有的std::shared\u ptr,等等。这是至关重要的。否则,只有使用共享iChive并以与序列化完全相同的顺序读取流,才能读回流

结果是,您的iChive需要以与Oachive完全相同的方式和顺序注册所有类型(我编写了一些使用mpl的方便助手来帮助我)

通过iAchive重新序列化也可以共享相同的iAchive,但是所有相同的条件都适用:

  • 您需要编写自己的流(以便可以重定向/重置)
  • 禁用存档标题
  • 有寄存器类型吗

是的,重复使用oarchive/iRChive是可能的,但这有点痛苦。但一旦你把它整理好,它就非常棒了。

这是我想出的解决方案。 它不需要实现您自己的流,并且允许为下一次序列化重用相同的内存块。 假设您为序列化安排了以下结构:

boost::iostreams::basic_array<char> sink; // target buffer 
boost::iostreams::stream<boost::iostreams::basic_array<char> > os;  // stream wrapper around it
boost::archive::binary_oarchive oa;  // archive which uses this stream
应该和在流中更改一些内部指针一样快。尽管如此,我还没有测试实际速度

用于尝试此操作的代码: 写入程序序列化传递给缓冲区的指针。 读卡器从同一缓冲区反序列化指针(读卡器和写卡器共享同一缓冲区)

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
甲级;
班主任{
char*buf;
内伦;
boost::iostreams::basic_阵列接收器;
boost::iostreams::stream操作系统;
boost::archive::binary_oarchive oa;
公众:
写入程序(char*_-buf,int-len):buf(_-buf),len(_-len),sink(buf,len),os(sink),oa(os){}
无效写入(A*A){
oa>a;
返回a;
}
无效重置(){
is.close();
is.open(src);
}
};
int main(int argc,字符**argv){
//记起
字符缓冲区[4096]={0};
写入器w(缓冲区,sizeof(缓冲区));
A*a1=新的A(5);
w、 写入(a1);
读卡器r(缓冲区,sizeof(缓冲区));
A*a2(空);
a2=r.read();
断言(*a1==*a2);

std::cout那么,如果要在写入内容后立即丢弃其内容,那么拥有缓冲区有什么意义呢?循环中到底包含了什么?如果声明
serial\u str
也不必清除它,因为它是在每个循环中创建的。@Tomalak抱歉,我应该在序列化每个对象之后提到,我正在使用boost::进程间::消息队列将其内容发送到另一个进程。@Omer:Aha!是的,您应该有。:)@Diego@Tomalak我很抱歉,我已经更新了我的代码来解决这些问题。谢谢,我考虑过了,但似乎应该有一个现成的解决方案?好吧,这里的问题是
back\u insert\u device
不可查找,所以你不能一开始就查找。哦,ic!我认为boost::iostreams::basic\u数组是可查找的,我不会我想用它来代替,看看会发生什么。是的,我正要提出这个建议,但我没有boost streams方面的经验。另外,请注意,创建
二进制文件并不那么昂贵,因为它只使用给定流中的streambuf(存储对它的引用),因此,只需缠绕流并创建一个新的
binary\u oarchive
即可保持性能。谢谢,这非常有帮助!您能否详细介绍一下为什么我必须编写自己的流,而不能只重用boost库中的流,以及如何着手构建它?我的自定义流与std::stringstr有什么不同eam?如果要将流指向不同的目标,您需要使用自己的流。对我来说,我考虑了文件,但它仍然适用于您的代码。每个新字符串都需要一个新流,因此如果您不编写自己的流,这意味着每个新字符串都需要一个新的oarchive。查看您的代码,这表明您正在重用strin通过清除它,这样就足够了
os.close();
os.open(sink);
#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/access.hpp>

class A;
class Writer {
    char *buf;
    int len;
    boost::iostreams::basic_array<char> sink;
    boost::iostreams::stream<boost::iostreams::basic_array<char> > os;
    boost::archive::binary_oarchive oa;
public:
    Writer(char *_buf, int _len): buf(_buf), len(_len), sink(buf, len), os(sink), oa(os) {}
    void write(A* a) {
        oa << a;
    }
    void reset() {
        os.close();
        os.open(sink);
    }
};
class Reader {
    char *buf;
    int len;
    boost::iostreams::basic_array_source<char> src;
    boost::iostreams::stream<boost::iostreams::basic_array_source<char> > is;
    boost::archive::binary_iarchive ia;
public:
    Reader(char *_buf, int _len): buf(_buf), len(_len), src(buf, len), is(src), ia(is) {}
    A* read() {
        A* a;
        ia >> a;
        return a;
    }
    void reset() {
        is.close();
        is.open(src);
    }
};

int main(int argc, char **argv) {
    // to memory
    char buffer[4096] = {0};

    Writer w(buffer, sizeof(buffer));
    A *a1 = new A(5);
    w.write(a1);

    Reader r(buffer, sizeof(buffer));
    A *a2 (NULL);
    a2 = r.read();

    assert(*a1 == *a2);
    std::cout << "Simple ok\n";

    // test reuse
    w.reset();
    r.reset();

    A *a3 (NULL);
    w.write(new A(10));
    a3 = r.read();

    assert(*a3 == A(10));
    std::cout << "Reuse ok\n";
};

class A
{
private:
  friend class boost::serialization::access;
  int i;

  template <typename Archive>
  void serialize(Archive& ar, const unsigned int version) {
    std::cout << "serialize A\n";
    ar & i;
  }
public:
  A(): i(0) {};
  A(int _i): i(_i) {};
  virtual bool operator==(const A&r) { return i == r.i; };

  virtual ~A() {};
  virtual void whoa() {std::cout << "I am A!\n";};
  virtual const char* me() { return "A"; };
};