我正在编写一个程序,从网络接收大量数据(不同大小的数据),处理它们并将它们写入内存。由于某些数据可能非常大,我目前的方法是限制使用的缓冲区大小。如果一个片段大于最大缓冲区大小,我将数据写入临时文件,然后以块的形式读取文件以进行处理和永久存储。
我想知道这是否可以改进。我已经阅读了一段时间的mmap,但我不是百分之百确定它是否可以帮助我。我的想法是使用mmap来读取临时文件。这有什么用?我关心的主要问题是,偶尔的大量数据不应该填满我的主内存,导致其他所有内容被换掉。
另外,您认为临时文件的方法是否有用?我是否应该这样做,或者,或许,我应该相信Linux内存管理器为我做这项工作?或者我应该完全做其他事情?
答案 0 :(得分:11)
Mmap可以在某些方面为您提供帮助,我将用一些假设的例子来解释:
第一件事:让我们说你的内存不足,你的应用程序拥有100MB的malloc内存,其中50%被换掉,这意味着操作系统不得不给交换文件写50MB,如果你需要读回来,你已经写了,占用了,然后再读回50MB你的交换文件。
如果内存只是mmap,操作系统不会将这条信息写入交换文件(因为它知道该数据与文件本身相同),相反,它只会划伤50MB信息(再次:假设你现在还没有写任何东西)以及那些信息。如果您需要再次读取该内存,操作系统将不是从交换文件中获取内容,而是从您正在编写的原始文件中获取内容,因此如果任何其他程序需要50MB交换,则它们可用。此外,交换文件操作根本没有开销。
让我们说你读了一个100MB的数据块,根据最初的1MB标题数据,你想要的信息位于偏移量75MB,所以你不需要1到1之间的任何东西。 74.9MB!您已经阅读了它,只是为了使您的代码更简单。使用mmap,您将只读取实际访问的数据(四舍五入或OS页面大小,大多为4kb),因此它只读取第一个和第75个MB。我认为制作一种比mmaping文件更简单,更有效的方法来避免磁盘读取非常困难。 如果由于某种原因你需要偏移37MB的数据,你可以使用它!您不必再次对其进行mmap,因为整个文件都可以在内存中访问(当然受到进程和内存空间的限制)。
所有文件mmap都由它们自己备份,而不是由交换文件备份,交换文件用于授予没有要备份文件的数据,这通常是数据malloc' ed或者由文件备份的数据,但是在程序通过msync调用实际告诉操作系统执行此操作之前,它已被更改并且[不能/不会]写回它。
请注意,您不需要将整个文件映射到内存中,您可以从任何地方开始映射任何数量(第二个arg是" size_t长度")(第6个arg - &# 34; off_t offset"),但除非您的文件可能很大,否则您可以放心地映射1GB的数据,即使系统只包含64mb的物理内存,但这是用于阅读,如果你打算写作,那么你应该更保守,只绘制你需要的东西。
映射文件将帮助您简化代码(您已经拥有内存中的文件内容,随时可以使用,内存开销少得多,因为它不是匿名内存)而且速度更快(您只会阅读您的程序访问的数据。)
答案 1 :(得分:2)
mmap与大文件的主要优点是在两个或多个文件之间共享相同的内存映射:如果使用MAP_SHARED
进行mmap,则只会将一次加载到内存中以用于所有将使用该文件的进程节省内存的数据。
但是AFAIK,mmap将整个文件映射到内存中(Here你可以找到mmap如何在文件大于物理内存和交换空间的情况下失败的例子。)所以如果你从一个进程访问文件,那么不会帮助你消耗物理内存。
答案 2 :(得分:1)
我相信mmap不要求所有数据同时存在于内存中 - 它使用页面缓存将最近使用的页面保留在内存中,其余部分保存在磁盘上。
如果您一次只读一个块,使用临时文件可能对您没有帮助,但如果您使用多个线程,进程或使用select / poll同时读取多个块,那么它可能会。