【发布时间】:2013-11-22 14:58:13
【问题描述】:
我在一个巨大的文件中随机读取数据(每次读取
我通常设置MADV_DONTNEED,但查看文档+信息似乎我需要FADV_NOREUSE。
我真的不明白madvise() 和fadvise() 是如何协同工作的。它们是同义词吗?我喜欢一个或另一个有关系吗?它们可以一起使用吗?它们是不同的内核子系统吗? FADV_NOREUSE 是我想要获得最佳性能的东西吗?
【问题讨论】:
我在一个巨大的文件中随机读取数据(每次读取
我通常设置MADV_DONTNEED,但查看文档+信息似乎我需要FADV_NOREUSE。
我真的不明白madvise() 和fadvise() 是如何协同工作的。它们是同义词吗?我喜欢一个或另一个有关系吗?它们可以一起使用吗?它们是不同的内核子系统吗? FADV_NOREUSE 是我想要获得最佳性能的东西吗?
【问题讨论】:
madvise() 和 posix_fadvise() 不是同义词。 madvise() 告诉内核(给出建议)如何处理现有内存区域,而 fadvise() 告诉内核如何处理文件数据的缓存(或未来缓存)。
例如,如果您使用 mmap() 匿名区域,您应该使用 madvise() 来提示内核不要换出 (MADV_RANDOM) 或仅在访问后换出。 (MADV_SEQUENTIAL)
如果您 mmap() 一个文件或文件的一部分,您可以使用 madvise() 或 fadvise() 来提示内核为您预读 (MADV_WILLNEED) 或释放该缓存 (MADV_DONTNEED) 或释放访问后(POSIX_FADV_NOREUSE,仅 fadvise())。
如果您使用文件而不将数据映射到进程内存(不使用 mmap()),则应仅使用 fadvise()。 madvise() 没有意义。
就内核子系统而言,在linux中,它是同一个子系统,只是引用内存页面和文件缓存的方式不同。请注意,这些只是提示,当内存不足时,内核可能会决定换出或重用缓存的数据,尽管有提示。只有 mlock() 和 mlockall() 可以防止这种情况发生。
在您的情况下,不提供任何提示可能会有所帮助,尤其是在某些页面被读取的次数多于其他页面时,因为内核会找出哪些页面是“热的”并尝试保留在内存中。
【讨论】:
如果您只是从文件中读取,那么您实际上也不需要。分页守护进程将自动释放与非脏或共享文件支持的映射关联的 RAM 页面。如果您继续调用madvise/MADV_DONTNEED,那么您就是在专门指示内核执行此操作。如果您在不久的将来再次访问同一页面,可能会影响性能。
fadvise 仅在您使用read/lseek 访问文件时才有用。对于mmapped 页面,它无效。
【讨论】:
MADV_DONTNEED 实现,它将丢弃修改过的页面,而不仅仅是非脏页面。 fadvise 适用于缓冲区缓存,这要归功于统一的虚拟内存系统确实影响映射文件。我不确定FADV_DONTNEED 是否也坏了(从未尝试过),但可以希望。如果它可以正常工作,那么它将非常有用。