2014-10-04 85 views
-1

我正在使用二进制文件来使用boost::binary_iarchive_ia恢复对象,但它太重(18GB),并且该对象将整个文件加载到内存。有没有办法通过部分读取文件(延迟加载)来避免内存使用?恢复对象延迟加载包含文件

我有什么:

std::ifstream ifs(filename); 
boost::archive::binary_iarchive_ia(ifs); 
MyObject obj; 
ia >> obj; 
+1

你有什么试过的?告诉我们你的程序如何加载文件。 'std :: ifstream'确实*不*自己将整个文件加载到内存中。 – Snps 2014-10-04 14:33:28

+0

使用seekg设置文件位置。 – 2014-10-04 14:35:18

+1

该代码本身不读取任何数据。 – 2014-10-04 14:36:15

回答

0

您可以使用mmap()将文件映射到你的地址空间。因此,文件太大无所谓,因为内核知道映射区域中的任何数据只是硬盘上文件的副本。因此,它甚至不需要在需要其他内存的情况下交换数据。内核只是懒惰地加载文件中你触碰它们时需要的部分,如果你不需要文件中的所有内容,那就特别好。

关于mmap()的好处是您可以将整个文件内容作为巨大的char数组访问,这对于许多用例来说非常方便。必须满足的唯一先决条件是您的进程以64位进程运行,否则您的虚拟地址空间将太小而无法将文件放入其中。

+0

糟糕。你不小心把问题颠倒了。原始文件从来不是问题(它一直在流)。问题在于反序列化试图将数据全部存储在内存中(例如向量)。所以唯一真正的解决方案是将这些数据放入(共享?)内存映射中。 *或者*可以修改反序列化代码以便即时转换为不同的磁盘格式,这将允许按照您的建议使用'mmap'方法。 – sehe 2014-10-04 20:01:46

1

升级我一个答案评论:

@cmaster得到非常接近,可以workm的做法,但他不小心把倒挂问题。

原始文件从来不是问题(它一直在流)。

问题是反序列化试图将数据全部放在内存中(例如矢量)。所以唯一真正的解决方案是

  • 是把这个数据放到一个(共享?)内存映射中。您可以使用Boost Interprocess中的分配器来帮助您实现这一点。这是一个很大的努力,但在概念上相对简单。

  • 可以修改反序列化代码以实时转换为不同的磁盘格式(而不是插入到例如该向量中),然后允许mmap作为cmaster建议的格式。

    换句话说,您可以“放宽”boost序列化实现,将数据从boost序列化转换为可直接在映射内存中使用的原始二进制格式。

+0

感谢您纠正我的疏忽:-)尽管如此,我会留下供参考。 – cmaster 2014-10-04 20:29:01