Linux文件预读对系统的影响

Linux系统很重要的一个性能提升点就是它的Pagecache, 因为内存比IO快太多了,所以大家都想进办法来利用这个cache。 文件系统也不例外,为了达到高性能,文件读取通常采用预读来预测用户的行为,把用户可能需要的数据预先读取到cache去,达到高性能的目的。

Linux各个发行版readahead的实现差异很大,我们这里重点讨论2.6.18, RHEL 5U4发行版的行为.文件预读的实现主要在mm/readahead.c中,代码才603行。 预读的流程大概是这样的,用户需要文件页面的时候入口函数do_generic_mapping_read会委托 page_cache_readahead来进行处理。它首先判断用户的IO是顺序的还是随机的,如果是随机的就没啥好预读. 如果是顺序的话,那么预读算法会根据用户上一次读取的页面的使用情况评估出预读的窗口,决定要读多少页面。读页面的模块会先检查要读取页面在 pagecache里面是否已经存在,如果不存在的话就需要发起IO请求,读取相应的页面。

这个预读的关键参数有3个: 用户的req_size, 预读算法评估出来的nr_to_read,以及实际上IO读取的页面数actual。

接下来我们就是要查看系统是如何运作的,所以我首先写了个systemtap脚本叫做ratop.stp来获取这些数据:

perl">
$ uname -r
2.6.18-164.el5
$ rpm -i kernel-debuginfo-common-2.6.18-164.el5.x86_64.rpm
$ rpm -i kernel-debuginfo-2.6.18-164.el5.x86_64.rpm
$ cat > ratop.stp
#!/usr/bin/stap -DMAXMAPENTRIES=10240
global total, skip
global req, to_read, actual
global __inode_filename
probe kernel.function("page_cache_readahead")
{
ino = __file_ino($filp)
req[ino]+=$req_size;
total++;
if($ra->flags & 0x2) skip++;
}
probe kernel.function("__do_page_cache_readahead").return
{
ino = __file_ino($filp)
to_read[ino]+= $nr_to_read;
if($return>0) actual[ino]+=$return;
}
probe timer.ms(5000)
{
if(total)
{
foreach( ino in req-)
{
    s0+= req[ino];
    s1+= to_read[ino]
    s2+= actual[ino];
}
printf("\\n%25s,  %5s%6d, %5s%6d, %5s%8d, %5s%8d, %5s%8d\\n\\n",
    ctime(gettimeofday_s()),
    "TOTAL:", total,
    "SKIP:", skip,
    "REQ:",s0,
    "TO_RD:",s1,
    "NR_RD:",s2
    )
  /* print header */
  printf("%25s %8s %8s %8s\\n",
       "FILENAME","REQ","TO_RD","NR_RD")
  foreach( ino in req- limit 20)
    printf("%25s %8d %8d %8d\\n", find_filename(ino), req[ino], to_read[ino], actual[ino]);
}
delete total;
delete skip;
delete req;
delete to_read;
delete actual;
}
probe generic.fop.open
{
__inode_filename[ino]= filename
}
function find_filename(ino)
{
return __inode_filename[ino]==""?sprint(ino):__inode_filename[ino];
}
probe begin
{
println("::");
}
CTRL +D
$ chmod +x ratop.stp
$ sudo ./ratop.stp
::
 Tue May 31 05:41:37 2011,  TOTAL:  2321, SKIP:	 0,  REQ:	6308, TO_RD:	6308, NR_RD:	1424
         FILENAME	  REQ	TO_RD	NR_RD
         056878.sst	   15	   15		0
         062889.sst	   13	   13		6
..
其中各个参数含义解释如下:
TOTAL: 系统共调用了多少次预读
SKIP: 由于页面在PAGECACHE中存在,略过多少次预读
REQ: 用户准备读取的页面数
TO_RD:预读算法告诉我们要读取的页面数
NR_RD:实际IO系统读取的页面数
这个脚本每5秒打印下系统目前的预读情况。

好吧,有了这个工具我们就可以做实验了。

先在一个终端下运行我们的脚本:

$ sudo ./ratop.stp
::

#等着出数据...

然后在另外一个终端下做实验:

#准备个数据文件
$ dd if=/dev/zero of=test count=1024 bs=4096
1024+0 records in
1024+0 records out
4194304 bytes (4.2 MB) copied, 0.008544 seconds, 491 MB/s
#清空pagecache
$ sudo sysctl vm.drop_caches=3
vm.drop_caches = 3
#第一次拷贝
$ cp test junk && sleep 5
#第二次拷贝
$ cp test junk

我们就可以在之前的脚本窗口里看到下面的信息:

#第一次拷贝test,我们可以看到 用户要1025个页面,预读决定读1084,但是实际IO读了1024,很合理,因为当时pagecache是空的
 Tue May 31 05:50:21 2011,  TOTAL:  1038, SKIP:     0,  REQ:    1039, TO_RD:    1320, NR_RD:    1109

                 FILENAME      REQ    TO_RD    NR_RD
                     test     1025     1084     1024
                       cp        3       36       18
...
#第二次拷贝test,我们可以看到 用户要1025个页面,预读决定读284,但是实际IO读了0,很合理,因为所有的页面在pagecache里面都已经存在
 Tue May 31 05:50:46 2011,  TOTAL:  1038, SKIP:   804,  REQ:    1039, TO_RD:     328, NR_RD:       0

                 FILENAME      REQ    TO_RD    NR_RD
                     test     1025      284        0
                       cp        3        4        0
  ...

Linux系统不仅为文件的读取提供自动预读,还提供了readahead这样的系统调用和工具,帮助用户主动预加载数据,我们演示下:

$ readahead junk
Preloaded 0 files (0 KB) in 5 ms

另外一个窗口说:

Tue May 31 05:57:45 2011,  TOTAL:  1044, SKIP:   805,  REQ:    1045, TO_RD:     348, NR_RD:       0

                 FILENAME      REQ    TO_RD    NR_RD
                     junk     1026      284        0
                readahead        3        4        0

Linux还支持对每个设备设定预读的默认大小,不同的大小可以用来控制预读的力度,用户可以自行改变:

$ pwd
/sys/block/sda/queue
$ cat read_ahead_kb
128
$ echo 256 |sudo tee  read_ahead_kb
256

后续我会用这个工具分析leveldb数据库的行为,欢迎关注!

总结: 如果actual读比用户req的要多很多, 那么我们的很多预读就浪费了,可以考虑减少预读的大小。

时间: 2024-10-11 08:04:51

Linux文件预读对系统的影响的相关文章

Linux内核的文件预读readahead

Linux的文件预读readahead,指Linux系统内核将指定文件的某区域预读进页缓存起来,便于接下来对该区域进行读取时,不会因缺页(page fault)而阻塞.因为从内存读取比从磁盘读取要快很多.预读可以有效的减少磁盘的寻道次数和应用程序的I/O等待时间,是改进磁盘读I/O性能的重要优化手段之一. 维基百科上关于readhead的介绍资料: readahead is a system call of the Linux kernel that loads a file's content

[转帖]监控Linux文件变化,防止系统被黑

监控Linux文件变化,防止系统被黑 https://os.51cto.com/art/201912/608702.htm改天尝试一下 inotify 运维服务器比较头疼的一个问题是系统被黑,沦为肉鸡或者矿机.除了加强安全基线配置,加强网络和端口加固,系统和应用bug修复,上IDS/IPS(入侵检测/防御系统)之外,另一个方面就是系统监控,一个完善准确的安全监控可以在主机层面及时发现入侵活动.予以告警以备及时处理. 作者:虫虫安全来源:今日头条|2019-12-31 14:00 收藏 分享 运维

Linux文件操作的常用系统函数说明

1. open打开文件 (man 2 open 查看) int open(const char *pathname, int flags); //pathname文件名(路径):flags打开模式,有O_RDONLY, O_WRONLY, O_RDWR int open(const char *pathname, int flags, mode_t mode); //该函数一般用于创建新文件,flags添加O_CREAT,比如:O_RDWR|O_CREAT int creat(const cha

Linux学习记录--文件IO操作相关系统编程

文件IO操作相关系统编程 这里主要说两套IO操作接口,分别是: POSIX标准 read|write接口,函数定义在#include<unistd.h> ISO C标准 fread|fwrite接口,函数定义在#include<stdio.h> 有书上说POSIX标准与ISO C标准的区别在于文件读写是否带缓冲区,我则不是很认同,因此POSIX标准下的IO操作也是带缓冲区的,至于这两个标准下的IO性能谁更加好则不一定,因为这和缓冲区的大小,以及用户逻辑有很大关系. POSIX标准

Linux内核模块编程与内核模块LICENSE -《详解(第3版)》预读

Linux内核模块简介 Linux内核的整体结构已经非常庞大,而其包含的组件也非常多.我们怎样把需要的部分都包含在内核中呢?一种方法是把所有需要的功能都编译到Linux内核.这会导致两个问题,一是生成的内核会很大,二是如果我们要在现有的内核中新增或删除功能,将不得不重新编译内核. 有没有一种机制使得编译出的内核本身并不需要包含所有功能,而在这些功能需要被使用的时候,其对应的代码被动态地加载到内核中呢?Linux提供了这样的一种机制,这种机制被称为模块(Module).模块具有这样的特点. 模块本

linux系列之1--文件系统+创建、删除文件和文件夹命令

1.概述 此系列是为自己做的一个总结,不是系统,主要目的是记录linux下我认为经常忘的方方面面. 2.文件系统 在linux下没有windows下的C.D盘的概念,而是目录和文件组成的一种层次结构,目录起点为根(root),其名为/.目录则为一个包含许多目录项的文件,在linux下所有东西都可以当成文件来看待,每个目录最少有2个文件 一个.代表自己,一个..代表上一层目录. linux下每个文件都具有属性信息,信息有:文件属性(普通文件.文件夹.可执行文件).文件大小.文件所有者.文件权限.最

linux在线预览pdf文件开发思路

准备:swftools,flexpaper 基本思路: 1,将pdf文件转化成swf文件 2,使用flexpaper预览swf文件 主要代码: 1,在linux中安装swftools.官网下载swftools 安装包,解压 2,./configure --prefix=安装路径 make install 执行完之后,执行pdf2swf -help 如果显示.说明安装成功 如果执行pdf2swf -help  显示commond not find 的话,可能需要配置swftools的环境变量,具体

linux文件经 windows系统 之后出现 权限缺失 的解决方法

把Linux下的文件拷贝到windows,再拷贝到Linux时,文件的权限丢失. 解决办法: 把文件压缩后,将压缩文件拷贝到windows系统上,再拷贝压缩文件到linux服务器,在目标linux服务器上执行解压. 压缩命令:tar cvf test.tar  filename 解压命令:tar xvf test.tar 可以在网上下载xmanager enterprise 4 linux管理软件,使用其中的xftp将文件拷贝到windows操作系统上,再拷贝到目标linux服务器上,解压..

Linux系统运维笔记(二),Linux文件编辑命令

Linux系统运维笔记 Linux文件编辑命令 首先我们使用命令 vi filename 打开一个文件,这个时候进入到的是命令模式 接下来我们按i,然后键盘随便输入写内容. 然后按ESC重新进入到命令模式. 在命令模式的情况下,我们按:,进入到了末行模式. 输入wq!,然后回车,强行保存退出. q! [强制退出不保存]q[退出不保存]wq[退出并保存后面也可以加个!] vi /etc/centos-release 查看centos系统版本 原文地址:https://www.cnblogs.com