Linux文件預讀對系統的影響

發表于:2014-01-20來源:IT博客大學習作者:Yu Feng點擊數: 標簽:linux
Linux系統很重要的一個性能提升點就是它的Pagecache, 因為內存比IO快太多了,所以大家都想進辦法來利用這個cache。 文件系統也不例外,為了達到高性能,文件讀取通常采用預讀來預測用戶的行為,把用戶可能需要的數據預先讀取到cache去,達到高性能的目的。

  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

  $ 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

原文轉自:http://blogread.cn/it/article/3670

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97