我有一个对象定义为:
std::unordered_map<std::string, std::vector<int>> large_obj;
它可以存储非常大量的数据(包含许多行)并且效果很好。但是,我想备份large_obj
到一个文件中,过一段时间,我会再次将它从文件加载到另一个对象。
什么是读取/写入此对象的最优化方法,而不是在预定义结构中写入文件中的每一行?
请记住:
- 多次调用 read() 比一次调用更昂贵
- 二进制文件比文本文件快。
哪些可以节省对象 I/O 的时间?
您可以尝试Boost::serialization。但请记住,这个库的向后兼容性很差。序列化后,您可以将所有存档数据写入文件。
序列化的本机方式是使用流运算符。这就是boost::serilization
大多数内部的工作方式。您可以重载您的类成员<<
和>>
运算符以写入和读取文本格式。但最好使用优雅稳定的解决方案。
我并不真正关心read()
and的开销write()
- 只需使用缓冲流和可以读取和写入的数据格式,而无需在数据流中来回跳过。
您正在写出的序列化流应该与您的数据表示足够接近,这样您就可以通过简单的复制来接管大块数据,但仍然足够抽象以允许从旧版本的数据格式或具有不同内部表示的机器上重建.
我通常定义一个标头,其中包括一个幻数、一个数据格式版本和一组捕获机器特定部分的值。对于你的情况,那将是
struct header {
char magic[4];
uint32_t endianness; // 0x01020304
uint32_t version; // incremented when format changes
// paranoia
uint8_t char_bit; // std::numeric_limits<char>::digits
// sizeofs for all types format is dependent on
uint8_t sizeof_int; // sizeof(int)
};
读回数据时,您将标头中的值与您期望的值进行比较——如果出现不匹配的情况,您可以添加处理此问题的反序列化代码。
对于行,我会使用类似的编码
uint16 string_length;
char string_data[]; // string_length bytes, padding if odd
uint16 vector_length;
int vector_data[]; // vector_length ints
这可以有效地保存和恢复。当您的需求发生变化时,只需增加版本号、定义新格式并调整解析器代码以创建新的内存表示。
也许,您可以尝试文档数据库。数据库引擎将部分处理性能。以MongoDB为例。
不可能有最优化的方法。您必须考虑权衡并衡量性能。Boost.Serialization 是一个不错的选择,但您必须有一套明确的要求,并且至少对最常见的用例进行一些性能测量。