程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了如何使用 os.posix_fadvise 防止 Linux 上的文件缓存?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决如何使用 os.posix_fadvise 防止 Linux 上的文件缓存??

开发过程中遇到如何使用 os.posix_fadvise 防止 Linux 上的文件缓存?的问题如何解决?下面主要结合日常开发的经验,给出你关于如何使用 os.posix_fadvise 防止 Linux 上的文件缓存?的解决方法建议,希望对你解决如何使用 os.posix_fadvise 防止 Linux 上的文件缓存?有所启发或帮助;

我有一个脚本,它通常在整个块设备上运行,如果读取的每个块都被缓存,它将驱逐其他应用程序正在使用的数据。为了防止这种情况发生,我添加了对使用 @H_144_3@mmap(2) 和 posix_fadvise(2) 的支持,逻辑如下:

指示不再需要块的函数:

def advise_dont_need(fd,offset,length):
    """
    Announce that data in a particular LOCATIOn is no longer needed.

    Arguments:
    - fd (int): file descriptor.
    - offset (int): Beginning of the unneeded data.
    - length (int): Length of the unneeded data.
    """
    # Todo: macOS support
    if hasattr(os,"posix_fadvise"):
        # posix_fadvise(2) states that "If the application requires that data
        # be consIDered for discarding,then offset and len must be
        # page-aligned." When this code aligns the offset and length,the
        # advised area is wIDened under the presumption it is better to discard
        # more memory than needed than to leak it which Could cause resource
        # issues.

        # If the offset is unaligned,extend it toWARD 0 to align it and adjust
        # the length to compensate for the change.
        aligned_offset = offset - offset % PAGE_SIZE
        length += offset - aligned_offset
        offset = aligned_offset

        # If the length is unaligned,wIDen it to align it.
        length -= length % -PAGE_SIZE

        os.posix_fadvise(fd,length,os.POSIX_FADV_DONTNEED)

读取文件的逻辑:

            with open(path,"rb",buffering=0) as file,\
              Progressbar("Reading file") as progress,timer() as read_loop:
                size = file_size(filE)

                if mmap_file:
                    # At the time of this wriTing,mmap.mmap in cpython uses
                    # st_size to determine the size of a file which will not
                    # work with every file type which is why file size
                    # autodetection (size=0) cAnnot be used here.
                    fd = file.fileno()
                    vIEw = mmap.mmap(fd,size,prot=mmap.pROT_READ)

                try:
                    while writer.error is None and hash_queue.error is None:
                        # Skip offsets that are already in the block map.
                        if offset in blocks:
                            while offset in blocks:
                                if mmap_file:
                                    advise_dont_need(fd,BLOCK_SIZE)

                                offset += BLOCK_SIZE

                            if not mmap_file:
                                file.seek(offset)

                        if mmap_file:
                            block = vIEw[offset:offset + BLOCK_SIZE]
                            advise_dont_need(fd,len(block))
                        else:
                            block = file.read(BLOCK_SIZE)

                        if not block:
                            break

                        bytes_read += len(block)

                        while hash_queue.error is None:
                            try:
                                hash_queue.put((offset,block),timeout=0.1)
                                offset += len(block)
                                progress.update(offset / sizE)
                                break
                            except queue.Full:
                                pass
                finally:
                    if mmap_file:
                        vIEw.close()

当我运行脚本并监控 free -h 的输出时,我可以看到缓冲区缓存使用量增加,尽管有这种逻辑。是我的逻辑不正确,还是 posix_fadvise(2)是这样的结果——建议与授权?

以下是一些日志,显示了在 BLOCK_SIZE 设置为 1048576 的脚本执行结束时的长度和偏移量值:

offset=107296587776; length=1048576
offset=107297636352; length=1048576
offset=107298684928; length=1048576
offset=107299733504; length=1048576
offset=107300782080; length=1048576
offset=107301830656; length=1048576
offset=107302879232; length=1048576
offset=107303927808; length=1048576
offset=107304976384; length=0

解决方法

您的脚本会导致应用程序数据被逐出并不完全准确。 posix_fadvise 的用法也不是这样解释的。 Linux 缓冲区和页面缓存的工作方式比这要复杂一些。

一、术语:

  • 缓冲区缓存 - 用于原始块设备访问,通常在文件系统之外。单位是块。测试这些的好方法是 dd if=/dev/...(在块设备上)of=/dev/null。随着时间的推移多次这样做 (1) 应该会显着减少第二次和以后的时间。

  • 页面缓存 - 用于基于文件系统的访问,单位传统上是完整的页面,由 inode 索引,因此每个文件只维护一个副本。测试这些的好方法是 cp 或 cat 或对大文件的任何访问,同样,随着时间的推移多次(1)应该显示时间减少和页面缓存使用增加(但对于同一文件不超过一次)

Linux 将尝试最大化两个缓存的使用。查看使用情况的常用方法是通过“free(1)”:

   [localhost ~]$ free
              @R_388_10586@l        used        free      shared  buff/cache   available
Mem:        3995408      633820     2241896        5820     1119692     3106196
Swap:       2138108      422408     1715700

这里的缓冲区缓存是单独虑的,不计为“已使用”,因为“已使用”是针对进程的。如果您确实需要进程/应用程序的内存,则优先虑并清除 buff/缓存。您可以通过对 malloc/memset 执行一个简单的程序并观察缓存大小缩小(到最低限度,即几兆字节)来测试这一点。其他版本的free用来显示+/-缓存,更清晰)

应用程序内存使用:由匿名内存(malloc(3) 等的总和)和文件映射内存(MAP_FILE 上的 mmap(2))组成。但是,后者算作文件缓存内存,而不是应用程序内存。只要此类文件映射内存是干净的(只读或尚未修改),就可以安全地逐出它。但是前者(匿名),如果需要驱逐,只能去swap(因为它没有后备文件)。

您使用的 posix_fadvise(2) 确实是建议。但是如果有足够的空闲内存,你的建议将是无效的——你说你不需要它,但实际上你确实读取了偏移量——所以 Linux 将缓存文件数据:有足够的内存来满足它,你可能最终会再次使用它,那么为什么不缓存它呢?它不应该导致任何匿名内存的驱逐或显着的内存压力 - 如果您的数据在缓存中找到,它会节省几个数量级的时间(保存它会将 I/O 保存到磁盘/闪存,这是 O(1000 +) 时间慢了。

另一种看待这个问题的方式:DONTNEED 的 posix_fadvise 通常是当有一个巨大的文件时,但你说你只会访问它的某些部分,所以你告诉系统 - 不要缓存某些范围我不会使用。一旦您确实使用它们,建议就无关紧要。

便说一句,您也可以直接将 madvise(2) 用于 mmap(2) ed 区域,使用 MADV_DONTNEED 等

大佬总结

以上是大佬教程为你收集整理的如何使用 os.posix_fadvise 防止 Linux 上的文件缓存?全部内容,希望文章能够帮你解决如何使用 os.posix_fadvise 防止 Linux 上的文件缓存?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。