c中的malloc vs mmap

时间:2009-11-15 23:35:41

标签: c malloc mmap

我构建了两个程序,一个使用malloc,另一个使用mmap。使用mmap的执行时间远远少于使用malloc

我知道例如当你使用mmap时,你会避免对系统的读/写调用。内存访问量较少。

但使用mmap优于malloc时,还有其他原因吗?

非常感谢

6 个答案:

答案 0 :(得分:13)

我假设您指的是使用mmap和malloc从文件中读取数据。在这种情况下,你几乎得到了重点:

  • 使用fread / fwrite你必须多次调用操作系统。
  • 使用mmap,您可以在一次操作中访问整个文件。这并不完全正确,因为操作系统可能一次将文件映射为memory page,但速度仍然快得多。

答案 1 :(得分:10)

mmap实际上并没有将文件加载到内存中,因此加载速度会更快,但编辑速度会慢一点。

另一点是mmap不使用任何内存,但它占用了地址空间。在64位机器上,大多数内存地址空间都没有内存,所以你可以加载大文件,比如5gb,你不想要malloc。

答案 2 :(得分:8)

看看人们,与普遍认为的相反,mmap确实是一个类似于malloc的内存分配函数。

mmaped文件是它的一个用途..你可以使用它作为内存分配函数传递-1作为文件描述符..

所以......常见的用法是将malloc用于小型对象,将mmap用于大型对象。

这是一个很好的策略..

我使用alloca()来仅为函数范围变量..

答案 3 :(得分:8)

malloc和mmap有时都很慢。这主要取决于使用模式:

MMAP: 内核分页子系统以页面大小为单位工作。这意味着,如果您想从文件中读取整个页面并希望重复这样做(良好的本地化),那么mmap就可以了。相反,如果您映射该5 Gb文件并进行分散访问,您将拥有很多内核交换页面。除了实际的I / O之外,页面管理还需要一些时间。如果您担心延迟,请避免使用此访问模式,因为Linux页面回收机制往往是突发性的并且会导致明显的滞后,并且缓存中毒会降低其他进程的速度。

的malloc: 当你需要不是以页面大小为单位的内存时,这很好。但你不能做像mlock()这样的事情。就I / O而言,速度在很大程度上取决于您的操作方式。 fread / fwrite可以在幕后映射页面,或者在用户空间中进行缓冲。本地化访问速度相当快。读/写直接通过内核,因此小的分布式访问仍然会由于缓存未命中而导致I / O,但是从内核 - >用户空间传输的实际数据将略微减少。我不知道这是否可以衡量。

除非使用mlock(),否则用户页面可能随时被换出/写回。这也需要时间。因此,在内存很少的系统上,映射最少内存的变体将获胜。对于Linux内核,每个系统都有太少的内存,因为未使用的页面用于缓存I / O,如果内存使用或I / O突发,内核可能需要花费大量时间才能使它们可用。

答案 4 :(得分:1)

mmap实际上并不读取该文件。它只是将其映射到地址空间。这就是为什么它如此之快,在您实际访问该地址空间区域之前没有光盘I / O.

malloc只是地址空间到内存的映射

答案 5 :(得分:-2)

  

通过mmap RAM未被授予。   地址空间被授予。

访问地址空间时会出现页面错误。 在页面大小的页面错误期间,通常为4096字节, 提供RAM。

还提供RAM内容。 如果通过文件支持地址空间 然后会出现文件内容。 如果通过MAP_ANONYMOUS支持地址空间 然后出现零初始化RAM。

通过上述两个恩赐进行描述。 首先,可以初始化所需的RAM。 其次,直到没有提供所需的RAM。

对于小于2兆字节的地址请求 通过malloc,程序中断被扩展。 虽然提供了接近程序中断的地址 程序中断无法签约。 因此,可能无法返回内核释放的RAM。 类比如下。 袜子可以在鞋子之前取下吗?

通过munmap调用内核RAM立即返回。 通过mmap和munmap使用交换概率得到缓解。 通过malloc程序中断扩展交换概率被煽动。

通过malloc可以分配小于页面大小的内存。 不连续的记忆变成了。 内核内存也可以碎片化。 两者都不完美。

在内核RAM上的任何空闲处理器上都可以被激活。 创建了2兆字节大小的透明大页面。 与512页故障相比,提供2M 当通过单页故障可以提供2M时 一个重要的表现恩惠。

通过mmap存在至少一个值得注意的祸害。 对于mmap支持,可以使用管道文件描述符。 错误不会成为。 但是,在内存地址中 管道提供的数据不会出现。

但是,如果使用MAP_ANONYMOUS 然后从管道文件描述符 进入mmap提供的地址可以读取数据。 虽然效率不高,但预期的结果却变得如此 由lseek失败返回和errno 可以识别管道附加文件描述符。

通过计算机可以解决整个兆字节和 运行基于磁盘的操作系统 然后malloc使用是必不可少的。 如果使用C库提供的getline函数 然后可能会使用malloc和free。

在内核控制的操作系统上 而不是mmap为什么要使用malloc? 与malloc相比; mmap看起来很复杂? 调用munmap 先前请求的地址空间量 还必须提供。 malloc使用更便携? malloc似乎更方便?

然而,如果需要性能,则使用mmap。

最后,但并非最不重要的是MAP_SHARED 然后与子代进程数据可以共享。 避免使用pthreads是至关重要的。 有时克隆也可以避免。

虽然主观, 列出的变量分配方法 在以下最受欢迎的内容中: 寄存器/堆栈; MMAP;全球; malloc的。 通过每个不同的恩惠和祸根成为。 通过一个足够复杂的程序; 使用三种或可能全部四种方法。