2009-11-15 55 views
31

我建了两个程序,一个使用malloc,另一个使用mmap。使用mmap的执行时间远小于使用mallocmalloc vs mmap C

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

但是在使用mmap而不是malloc时,还有什么其他原因可以利用吗?

非常感谢

+0

我可以假设你的malloc程序使用读/写或者fread/fwrite在你的mmap文件上做一些I/O操作吗? – Suppressingfire 2009-11-15 23:45:23

+0

是的,实际上我正在使用malloc,mmap和使用常规R/W调用进行读/写操作。使用R/W调用的 比使用malloc快,我猜是因为访问磁盘比内存快。 – Peter 2009-11-16 00:03:12

+6

这并不是说访问磁盘比内存快。几乎总是,内存比磁盘快得多,而malloc不是花费时间。 mmap代码更快,因为对于您的程序,mmap导致的磁盘访问更少,或者磁盘访问效率更高,与您比较的任何读取和写入无关。例如,写入整个文件实际上会将所有这些字节发送到磁盘。 mmap只是意味着*如果*您修改了'mmap' ed数据,*然后*操作系统将写入更改。所以如果你最终没有修改整个文件,你可能只写过一小部分。 – 2009-11-16 00:39:02

回答

11

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

  • 使用fread/fwrite您必须对OS进行多次调用。
  • 使用mmap,您似乎可以在一次操作中访问整个文件。这并不完全正确,因为操作系统可能一次映射一个memory page文件,但它仍然快很多。
+1

为了补充说明,'fread'被缓冲,这意味着如果它前面有一个fseek,它将总是完全填充他的缓冲区。我有一个程序在每个读取8192字节的记录(大小为32)之前按顺序读取一个文件,但是在fseek之前。所以它最终读取的数据量比必要的多256倍,再加上读取内容总是两次。用'mmap'你没有(可见)。 – 2010-10-22 13:44:20

7

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

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

0

mmap实际上没有读取文件。它只是将其映射到地址空间。这就是它速度如此之快的原因,除非您真正访问该地址空间区域,否则没有光盘I/O。

的malloc是一个简单的地址空间,内存映射

6

看看乡亲,与一般认为,MMAP的确是类似的malloc内存分配函数..

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

所以..常见的用途是用于微小物体和MMAP路数的malloc ..

这是一个很好的战略..

我使用ALLOCA()为唯一的功能范围内的变量..

+5

正常情况下,分配器将根据用'malloc'提出的区域大小本身使用'mmap'。在Solaris上,当请求超过128K时,您将获得一个'MAP_ANON'内存映射块。在OS/X上,如果我没有记错,限制为64K,其他系统和分配库将具有其他值。 – 2010-10-22 13:48:59

8

两个malloc和MMAP是在时间慢。这主要取决于使用模式:

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

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

除非mlock()被编辑,否则用户页面可能随时被换出/回写。这也需要时间。所以在内存很少的系统上,映射最少内存的变体将会获胜。使用Linux内核时,每个系统的内存太少,因为未使用的页面用于缓存I/O,如果内存使用或I/O突发,内核可能需要很长时间才能使其可用。

-3

由mmap RAM未被授予。 地址空间被授予。

当访问地址空间时,页面错误变为。 在页面大小的页面错误期间,通常提供4096个字节,提供了 RAM。

也提供RAM内容。 如果通过文件的地址空间支持 则文件内容将出现。 如果通过MAP_ANONYMOUS地址空间被支持 ,则出现零初始化RAM。

通过上面的两个插图进行描述。首先,正如所期望的RAM可以被初始化。其次,直到不提供所需的RAM。

对于小于2兆字节的地址请求 by 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的。 由每个不同的福恩和巴恩成为。 由一个足够复杂的程序; 三种或可能全部四种方法被使用。

+2

这个答案需要一些严肃的编辑。 – 2016-03-25 03:17:38

+2

不过,它只是需要'海盗说'是 makin'correctus in you headin'。 – 2017-04-14 18:19:38