我的应用程序需要从MegaBytes加载到几十千兆字节的二进制数据(多个文件)到RAM中。经过一番搜索,我决定使用std::vector<unsigned char>
来达到这个目的,虽然我不确定它是最好的选择。
我会为每个文件使用一个向量。由于应用程序以前知道文件大小,因此会调用reserve()
为其分配内存。有时候应用程序可能需要完全读取一个文件,而在其他一些文件中只需要部分文件和vector的迭代器就可以了。它可能需要从RAM中卸载文件并将其他文件放到适当位置,std::vector::swap()
和std::vector::shrink_to_fit()
将非常有用。我不想在处理低级内存分配方面付出艰苦的努力(否则会与C一起使用)。
我有一些问题:
reserve()
并查找错误吗?怎么样?仅当请求的大小大于reserve()
时,引用仅说std::vector::max_size
会引发异常。std::vector<unsigned char>
是否适用于将大量二进制数据存入RAM?我担心std::vector::max_size
,因为它的参考说它的价值取决于系统或实施限制。我认为系统限制是免费RAM,是不是?所以,没问题。但是实现限制怎么样?是否存在任何可能妨碍我做我想做的实现?案例肯定,请给我一个替代方案。sysinfo()
并基于可用RAM推断的最佳方法吗?Obs。:应用程序的这一部分必须能够获得更高的性能(低处理时间/ CPU使用率和RAM消耗)。我很感激你的帮助。
答案 0 :(得分:6)
如何知道是否有足够的内存空间来加载一个文件?
你不会事先知道。将加载过程包装在try-catch中。如果内存耗尽,则抛出std::bad_alloc
(假设您使用默认分配器)。假设内存在加载代码中足够,并处理异常处理程序中缺少的内存。
但实施限制呢? ... 是否存在任何可能妨碍我做我想做的实现?
您可以在运行时检查std::vector::max_size
以进行验证。
如果程序是用64位字大小编译的,那么向量很可能有足够的max_size几百GB。
应用程序的这一部分必须获得更多性能
这与
冲突我不想在处理低级别内存分配方面付出艰苦的努力
但是如果低级内存对于性能来说是值得的,那么你可以memory-map将文件放入内存。
我已经阅读了一些SO问题,以避免它们出现在需要高性能且更喜欢处理返回值的应用程序上,错误等等
不幸的是,如果您使用标准容器,则不能选择非投掷内存分配。如果您对异常过敏,那么您必须使用向量的另一个实现 - 或者您决定使用的任何容器。但是,您不需要任何带有mmap的容器。
不处理异常会破坏性能吗?
幸运的是,与从磁盘读取数百GB相比,运行时异常成本微不足道。
运行sysinfo()并在加载文件之前检查空闲RAM是否更好?
sysinfo
调用可能比处理异常要慢(我没有测量过,这只是一个猜想) - 并且它不会告诉您可能存在的特定于进程的限制。
而且,重复尝试加载文件,捕获异常并尝试加载较小的文件(需要递归?)看起来很难并且代价高昂。
不需要递归。如果您愿意,可以使用它;它可以用尾调用来编写,可以优化掉。
关于内存映射:我前一段时间看过它,发现无聊处理。需要使用C的open()和所有内容,然后再告诉std :: fstream。
映射内存后,它比std::fstream
更容易使用。您可以跳过复制到矢量部分,只需使用映射的内存,就好像它是已经存在于内存中的数组一样。
看起来使用std :: fstream部分读取文件的最佳方法是派生std :: streambuf
我不明白为什么你需要得到任何东西。只需使用std::basic_fstream::seekg()
跳到您想要阅读的部分。
答案 1 :(得分:2)
作为@user2097303's answer的补充,我想补充说vector
保证连续分配。对于长时间运行的应用程序,这将导致内存碎片,最终,将不再存在连续的内存块,尽管在块之间,有足够的空间是免费的。
因此,最好将数据存储到deque