Linux文件预读分析以及评估对系统的影响

标签: Linux 工具介绍 调优 readahead systemtap | 发表时间:2011-05-31 14:11 | 作者:Yu Feng Adam
出处:http://blog.yufeng.info

原创文章,转载请注明: 转载自Erlang非业余研究

本文链接地址: 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来获取这些数据:

$ uname -r
2.6.18-164.el5

$ sudo rpm -i kernel-debuginfo-common-2.6.18-164.el5.x86_64.rpm
$ sudo 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这样的系统调用和工具,帮助用户主动预加载数据,我们演示下:

$ sudo sysctl vm.drop_caches=3
vm.drop_caches = 3
$ cat > file.lst
test
junk
CTRL+D
$ readahead file.lst
Preloaded 2 files (409600 KB) in 863 ms
$ cp test /dev/null

另外一个窗口说:

# 说明文件确实被预加载了。
Tue May 31 08:51:08 2011,  TOTAL:  1038, SKIP:   804,  REQ:    1039, TO_RD:     392, NR_RD:      29

                 FILENAME      REQ    TO_RD    NR_RD
                     test     1025      284        0
                     cp        3       36       18

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

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

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

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

玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

相关 [linux 文件 分析] 推荐:

Linux上Core Dump文件的形成和分析

- - CSDN博客推荐文章
Core,又称之为Core Dump文件,是Unix/Linux操作系统的一种机制,对于线上服务而言,Core令人闻之色变,因为出Core的过程意味着服务暂时不能正常响应,需要恢复,并且随着吐Core进程的内存空间越大,此过程可能持续很长一段时间(例如当进程占用60G+以上内存时,完整Core文件需要15分钟才能完全写到磁盘上),这期间产生的流量损失,不可估量.

在Linux上使用logwatch分析监控日志文件

- - SegmentFault 最新的文章
在维护Linux服务器时,经常需要查看系统中各种服务的日志,以检查服务器的运行状态. 如登陆历史、邮件、软件安装等日志. 系统管理员一个个去检查会十分不方便;且大多时候,这会是一种被动的检查,即只有在发现系统运行异常时才会想到去查看日志以获取异常的信息. 那么如何主动、集中的分析这些日志,并产生报告,定时发送给管理员就会显得十分重要.

Linux文件预读分析以及评估对系统的影响

- Adam - Erlang非业余研究
原创文章,转载请注明: 转载自Erlang非业余研究. 本文链接地址: Linux文件预读分析以及评估对系统的影响. Linux系统很重要的一个性能提升点就是它的Pagecache, 因为内存比IO快太多了,所以大家都想进办法来利用这个cache. 文件系统也不例外,为了达到高性能,文件读取通常采用预读来预测用户的行为,把用户可能需要的数据预先读取到cache去,达到高性能的目的.

Linux 文件结构

- Shiina Luce - OSMSG
想了解 Linux 文件系统树形结构,却又不愿翻阅 FHS 的朋友,可以参考 skill2die4 制作的这张简图. 此图算是 FHS 的图形化版本,简要的说明了 Linux 系统中各个目录的用途及层级关系,适合初学者使用参考. 不过其中较新的如 /run 目录并未在其中出现. 做为参考,这是 Fedora 16 Beta i686 上的文件结构:.

Linux 性能分析工具 nmon for Linux

- - CSDN博客架构设计推荐文章
nmon 是 Nigel's performance Monitor for Linux on POWER, x86, x86_64, Mainframe & now ARM (Raspberry Pi) 的缩写,意思是 Nigel(nmon 的作者是 Nigel Griffiths) 的 Linux 性能检测器.

linux 启动流程分析

- - 编程学习网
今天,一起探讨操作系统的启动流程. 因为在BIOS阶段,计算机的行为基本上被写死了,程序员可以做的事情并不多;但是,一旦进入操作系统,程序员几乎可以定制所有方面. 所以,这个部分与程序员的关系更密切. 我主要关心的是Linux操作系统,它是目前服务器端的主流操作系统. 下面的内容针对的是Debian发行版,因为我对其他发行版不够熟悉.

Linux 2.6 中的文件锁

- Mountain - 小程序员的草稿箱
在多任务操作系统环境中,如果一个进程尝试对正在被其他进程读取的文件进行写操作,可能会导致正在进行读操作的进程读取到一些被破坏或者不完整的数据;如果两个进程并发对同一个文件进行写操作,可能会导致该文件遭到破坏. 因此,为了避免发生这种问题,必须要采用某种机制来解决多个进程并发访问同一个文件时所面临的同步问题,由此而产生了文件加锁方面的技术.

Linux 文件结构 — LinuxTOY

- oak - linuxtoy.org
想了解 Linux 文件系统树形结构,却又不愿翻阅 FHS 的朋友,可以参考 skill2die4 制作的这张简图. 此图算是 FHS 的图形化版本,简要的说明了 Linux 系统中各个目录的用途及层级关系,适合初学者使用参考. 不过其中较新的如 /run 目录并未在其中出现.

linux tcpdump命令以及结果分析

- - CSDN博客系统运维推荐文章
tcpdump能帮助我们捕捉并保存网络包,保存下来的网络包可用于分析网络负载情况,包可通过tcpdump命令解析,也可以保存成后缀为pcap的文件,使用wireshark等软件进行查看. 1.针对特定网口抓包(-i选项). 当我们不加任何选项执行tcpdump时,tcpdump将抓取通过所有网口的包;使用-i选项,我们可以在某个指定的网口抓包:.