我知道我可以从Linux文件系统缓存中删除所有内容,但是有没有办法仅删除一个特定文件?还是阻止文件被缓存?还是告诉进程不要缓存它写入的任何文件?
我有一个读取很多小文件并写入一个大文件的过程。我想将小的文件保留在缓存中以避免磁盘寻道,而且我也不在乎缓存大文件。
我知道我可以从Linux文件系统缓存中删除所有内容,但是有没有办法仅删除一个特定文件?还是阻止文件被缓存?还是告诉进程不要缓存它写入的任何文件?
我有一个读取很多小文件并写入一个大文件的过程。我想将小的文件保留在缓存中以避免磁盘寻道,而且我也不在乎缓存大文件。
Answers:
我从2012年开始发现了一种方法,该方法在此邮件线程中讨论了对Linux内核的提议补丁,标题为:Re:[RFC Patch] fs:实现每个文件丢弃缓存。
摘抄Cong>这是实现按文件删除缓存的草稿补丁。
有趣。那么我可以从流程外部执行此操作吗?我是SysAdmin,所以我的观点是从在系统处于压力下时注意到,发现和修复性能问题开始的。
Cong> It introduces a new fcntl command F_DROP_CACHES to drop Cong> file caches of a specific file. The reason is that currently Cong> we only have a system-wide drop caches interface, it could Cong> cause system-wide performance down if we drop all page caches Cong> when we actually want to drop the caches of some huge file.
如何判断一个文件使用了多少缓存?在繁忙的系统上运行时,这会对性能产生什么影响?这个补丁对我们有什么好处,因为我认为一旦系统受到内存压力,虚拟机就应该已经丢弃了缓存...
Cong>以下是此补丁的小型测试用例:
螺纹包括测试用例和实际的补丁几个文件在Linux内核中,其增加了额外的功能,fs/drop_caches.c
叫做drop_pagecache_file(struct file *filp)
。然后可以通过前端工具,fnctl.c
通过命令访问此功能F_DROP_CACHES
。这种情况调用此函数:
file_drop_caches(filp, arg);
它处理与给定文件关联的所有缓存的删除。从文件include/linux/mm.h
:
void file_drop_caches(struct file *filp, unsigned long which);
那么可以使用吗?
我没有发现任何证据表明该修补程序已经进入了主要的Linux内核代码存储库,因此仅当您愿意自己重新编译Linux内核时,此选项才可用。
在同一线程中,另一个用户提到了一个完全不同的方法,该方法使用dd
。
测试出来这是有用的功能。虽然还没有提供
以下是该补丁中的示例:POSIX_FADV_DONTNEED
?一年前,此功能已添加到GNU dd(8.11)中。
建议删除整个文件的缓存
$ dd if=ifile iflag=nocache count=0
确保整个文件的删除缓存
$ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
删除部分文件的缓存
$ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
仅使用预读缓存流数据
$ dd if=ifile of=ofile iflag=nocache oflag=nocache
我不是100%肯定如何进行测试的,但是我想出了以下方法。
制作一个100MB的文件
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
使用跟踪文件访问 fatrace
$ sudo fatrace | grep sample.txt
运行,top
以便我们可以监视内存使用情况,注意可用数量。
$ top
打开文件,现在记下可用内存量。注意fatrace
文件的sample.txt
。
$ cat sample.txt > /dev/null
从内存中删除文件,现在记下可用内存量。注意的输出fatrace
。
$ sudo dd of=/home/saml/tst/162600/sample.txt \
oflag=nocache conv=notrunc,fdatasync count=0
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
1+0 records in
1+0 records out
104857600 bytes (105 MB) copied, 7.37996 s, 14.2 MB/s
$ ls -l sample.txt
-rw-rw-r--. 1 saml saml 104857600 Oct 17 22:54 sample.txt
在2号航站楼:
$ top
...
KiB Mem: 7968336 total, 6900956 used, 1067380 free, 267080 buffers
...
在3号航站楼:
$ sudo fatrace | grep sample.txt
现在打开文件,sample.txt
并记下RAM的数量。在1号航站楼。
$ cat sample.txt > /dev/null
在2号航站楼:
KiB Mem: 7968336 total, 7011896 used, 956440 free, 267336 buffers
注意fatrace
端子#3中的输出:
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): RC /home/saml/tst/162600/sample.txt
现在从终端4中的RAM中删除文件:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
oflag=nocache conv=notrunc,fdatasync count=0
注意fatrace
端子2 的输出:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
请注意端子3中的RAM:
KiB Mem: 7968336 total, 6908364 used, 1059972 free, 267364 buffers
因此,似乎RAM中文件消耗的所有内存都已释放。
感谢@frostchutz的评论,还有另一个工具,Python脚本,名为Python脚本,[pyadvise][4]
它提供了比上述dd
方法简单得多的界面。该脚本使用相同的posix_fadvise(2)
界面。
$ sudo pyadvise --help
Usage:
pyadvise [options] [FILE]..
Options:
-h, --help show this help message and exit
-w, --willneed The specified files will be accessed in the near future
-s, --sequential The application expects to access the specified files
sequentially (with lower offsets read before higher ones)
-d, --dontneed The specified files will not be accessed in the near
future
-r, --random The specified files will be accessed in random order
-o, --noreuse The specified files will be accessed only once. Under
Linux, this operation is a no-op; see contrib/copyfileobj-
fadvise.py in the python-fadvise source tree for an
example on how to achieve approximately the same effect
-n, --normal Indicates that the application has no advice to give about
its access pattern for the specified files. If no advice
is given for an open file, this is the default assumption
-v, --verbose Explain what is being done
如果我们重复上述测试并pyadvise
代替dd
:
$ pyadvise -d /home/saml/tst/162600/sample.txt
我注意到使用时与以前一样消耗了相同的RAM dd
。
dd
为我工作。我最终以chris-lamb.co.uk/projects/python-fadvise自己结束了,这在更明显的命令中也是一样。
python-fadvise
容易得多,我添加了一个显示示例dd
。
os.posix_fadvise()
在Python的标准库中有。
扩展@geekosaur的答案,您可以O_DIRECT
通过使用LD_PRELOAD和此处的程序来强制使用:http : //arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html
该代码将强制O_DIRECT
所有文件。但是,只需在其中添加一些更多的strncmp逻辑__do_wrap_open
就可以有选择地应用O_DIRECT。
免责声明:我尚未对此进行测试。
如果要强制文件始终使用O_SYNC,则可以在扩展属性中将其标记为chattr +S $file
:
男人聊天:
修改具有“ S”属性集的文件时,所做的更改将被同步写入磁盘。这等效于应用于文件子集的“ sync”安装选项。
O_SYNC强制将数据+元数据写入磁盘缓冲区,但仍会通过页面缓存。O_DIRECT绕过页面缓存。
但是请注意,使用O_DIRECT打开它会损害性能,如果只是附加大文件,差异可能会很小。但是,如果将大文件在任意位置重写,O_DIRECT会对性能产生重大影响,即使考虑到将其存储在高速缓存中也可能会从高速缓存中读取一些小的读取文件。
如果您拥有将所有小文件保存在其中的内存,则可以采用其他方法解决该问题。确保小文件始终位于ram中,然后建议将它们复制到tmpfs:
tmpfs将所有内容放入内核内部高速缓存中,并进行扩展和收缩以容纳其中包含的文件
chattr +S
与是不同的东西O_DIRECT
,与是相同的东西O_SYNC
。O_DIRECT
导致读取不被缓存(这是关于这个问题的意思),并且写入不被缓存(不保证)。O_SYNC
仅导致不缓冲写操作。
O_DIRECT
为O_SYNC
会使您的答案内部一致,但考虑到该问题仍然是错误的。