1. 程式人生 > >系統技術非業餘研究 » Linux下非同步IO(libaio)的使用以及效能

系統技術非業餘研究 » Linux下非同步IO(libaio)的使用以及效能

Linux下非同步IO是比較新的核心裡面才有的,非同步io的好處可以參考這裡.
但是文章中aio_*系列的呼叫是glibc提供的,是glibc用執行緒+阻塞呼叫來模擬的,效能很差,千萬千萬不要用。

我們今天要說的是真正的原生的非同步IO介面. 由於這幾個系統呼叫glibc沒有提供相應的封裝,所以libaio來救急了:

libaio專案: http://oss.oracle.com/projects/libaio-oracle/

This is a library for accessing the new AIO system calls (asynchronous i/o) for the Linux kernel. It is a thin, state-keeping wrapper that conforms to the Single Unix Specification for aio_read, aio_write, aio_error, aio_return and aio_suspend functions, and also implements lio_listio and aio_reap for batch processing.

This library requires a kernel with the new AIO code and a recent version of the libaio userspace library.

libaio提供了4個函式: io_cancal, io_destroy, io_getevents, io_setup,io_submit來提供服務,具體的可以參看man io_*

淘寶的雕樑同學寫了這篇文章介紹了libaio如何和event一起高效工作:看這裡

使用很簡單的,在RHEL 5U4上只要安裝下開發包就好:

$ sudo yum install libaio-devel 

其實大家會比較關心效能。 fio 測試工具支援同步(pread/pwrite)和非同步(libaio)的測試,那我們比較下:

為了減低底層硬體(如raid)cache的影響,我們用總共2G左右的檔案做隨機讀寫操作, 完全隨機的讀寫,塊大小128K, directio繞過OS page buffer系統, 總共跑1分鐘。

在非同步io操作的時候只用一個程序保持io佇列的長度為16, 同步io開16個程序,保持同樣的佇列這樣會公平些。

測試機器配置:

$ summary 
# Aspersa System Summary Report ##############################
     Release | Red Hat Enterprise Linux Server release 5.4 (Tikanga)
      Kernel | 2.6.18-164.el5
  Processors | physical = 2, cores = 8, virtual = 16, hyperthreading = yes
      Speeds | 16x2261.053
      Models | 16xIntel(R) Xeon(R) CPU E5520 @ 2.27GHz
      Caches | 16x8192 KB
# Memory #####################################################
       Total | 23.53G
...

先開始非同步IO的測試:

$ cat aio-bench
[global]
ioengine=libaio
direct=1
rw=randrw
bs=128k
directory=.
ioscheduler=deadline
time_based
runtime=60

[libaio.dat]
size=2g
iodepth=16

$ sudo fio aio-bench  
libaio.dat: (g=0): rw=randrw, bs=128K-128K/128K-128K, ioengine=libaio, iodepth=16
fio 1.50.2
Starting 1 process
Jobs: 1 (f=1): [m] [100.0% done] [31462K/34595K /s] [240 /263  iops] [eta 00m:00s]
libaio.dat: (groupid=0, jobs=1): err= 0: pid=25892
  read : io=1795.4MB, bw=30575KB/s, iops=238 , runt= 60129msec
    slat (usec): min=14 , max=130031 , avg=25.13, stdev=1084.85
    clat (usec): min=178 , max=1959.4K, avg=66231.82, stdev=154044.70
     lat (msec): min=1 , max=1959 , avg=66.26, stdev=154.04
    bw (KB/s) : min=22721, max=95552, per=100.66%, avg=30775.78, stdev=7306.36
  write: io=1836.8MB, bw=31280KB/s, iops=244 , runt= 60129msec
    slat (usec): min=12 , max=55571 , avg=18.50, stdev=458.33
    clat (usec): min=252 , max=377818 , avg=658.98, stdev=7612.29
     lat (usec): min=266 , max=377832 , avg=677.73, stdev=7626.25
    bw (KB/s) : min=20223, max=94275, per=100.74%, avg=31511.06, stdev=7334.59
  cpu          : usr=0.13%, sys=0.72%, ctx=28484, majf=0, minf=24
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=99.9%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.1%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued r/w/d: total=14363/14694/0, short=0/0/0
     lat (usec): 250=0.01%, 500=46.44%, 750=1.91%, 1000=0.39%
     lat (msec): 2=1.55%, 4=0.39%, 10=3.07%, 20=5.66%, 50=20.97%
     lat (msec): 100=14.42%, 250=4.46%, 500=0.19%, 750=0.02%, 1000=0.01%
     lat (msec): 2000=0.51%

Run status group 0 (all jobs):
   READ: io=1795.4MB, aggrb=30575KB/s, minb=31309KB/s, maxb=31309KB/s, mint=60129msec, maxt=60129msec
  WRITE: io=1836.8MB, aggrb=31279KB/s, minb=32030KB/s, maxb=32030KB/s, mint=60129msec, maxt=60129msec

Disk stats (read/write):
  sda: ios=15108/20465, merge=4704/4206, ticks=969251/16763, in_queue=989615, util=99.84%


#通過strace可以看到
...
26112 io_submit(47710156091392, 1, {{(nil), 0, 1, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 1, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 1, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 1, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 1, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 1, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 1, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_submit(47710156091392, 1, {{(nil), 0, 0, 0, 9}}) = 1
26112 io_getevents(47710156091392, 1, 1, {{(nil), 0x18ad9f00, 131072, 0}}, NULL) = 1
證明確實aio在工作。

再看下同步IO的測試:

$ cat psync-bench
[global]
ioengine=psync
direct=1
rw=randrw
bs=128k
directory=.
ioscheduler=deadline
time_based
runtime=60

[file1]
numjobs=16

$ sudo fio psync-bench
file1: (g=0): rw=randrw, bs=128K-128K/128K-128K, ioengine=psync, iodepth=1
...
file1: (g=0): rw=randrw, bs=128K-128K/128K-128K, ioengine=psync, iodepth=1
fio 1.50.2
Starting 16 processes
Jobs: 16 (f=16): [mmmmmmmmmmmmmmmm] [100.0% done] [31854K/31723K /s] [243 /242  iops] [eta 00m:00s]
file1: (groupid=0, jobs=1): err= 0: pid=26145
  read : io=118144KB, bw=1967.1KB/s, iops=15 , runt= 60036msec
    clat (msec): min=3 , max=1531 , avg=64.36, stdev=133.07
     lat (msec): min=3 , max=1531 , avg=64.36, stdev=133.07
    bw (KB/s) : min=   84, max= 6083, per=7.02%, avg=2205.14, stdev=807.87
  write: io=121984KB, bw=2031.9KB/s, iops=15 , runt= 60036msec
    clat (usec): min=264 , max=153817 , avg=660.30, stdev=6100.86
     lat (usec): min=265 , max=153818 , avg=660.53, stdev=6100.88
    bw (KB/s) : min=   84, max= 5765, per=7.32%, avg=2311.53, stdev=1256.97
  cpu          : usr=0.00%, sys=0.05%, ctx=1877, majf=0, minf=32
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued r/w/d: total=923/953/0, short=0/0/0
     lat (usec): 500=46.75%, 750=2.40%, 1000=0.43%
     lat (msec): 2=1.01%, 4=0.16%, 10=2.99%, 20=4.69%, 50=20.31%
     lat (msec): 100=15.41%, 250=5.28%, 500=0.21%, 2000=0.37%
...
省去中間15個檔案
...
Run status group 0 (all jobs):
   READ: io=1844.0MB, aggrb=31411KB/s, minb=1699KB/s, maxb=2186KB/s, mint=60001msec, maxt=60114msec
  WRITE: io=1852.9MB, aggrb=31562KB/s, minb=1620KB/s, maxb=2325KB/s, mint=60001msec, maxt=60114msec

Disk stats (read/write):
  sda: ios=15756/20708, merge=4553/4159, ticks=979074/16483, in_queue=999501, util=99.83%

#通過strace可以看到
26195 pwrite(20, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072, 5242880) = 131072
26195 pwrite(20, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072, 23855104) = 131072
26195 pwrite(20, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072, 7864320) = 131072
26195 pread(20,  <unfinished ...>
證明確實是pread/pwrite操作的。

從上面的資料我們可以看出,最後的結果都是裝置的IO能力將近100%的被使用,二個測試的吞吐量差不多。 但是如果從當個程序提交的吞吐量來看的話,一個aio程序相當於16個同步程序的能力,也就是說如果大家都是一個程序在幹活的話,那麼aio的能力要比同步的好太多了。

大家玩得開心!

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

相關推薦

系統技術業餘研究 » Linux非同步IO(libaio)的使用以及效能

Linux下非同步IO是比較新的核心裡面才有的,非同步io的好處可以參考這裡. 但是文章中aio_*系列的呼叫是glibc提供的,是glibc用執行緒+阻塞呼叫來模擬的,效能很差,千萬千萬不要用。 我們今天要說的是真正的原生的非同步IO介面. 由於這幾個系統呼叫glibc沒有提供相應的封裝,所以l

系統技術業餘研究 » Linux系統呼叫sync_file_range

我們在做資料庫程式或者IO密集型的程式的時候,通常在更新的時候,比如說資料庫程式,希望更新有一定的安全性,我們會在更新操作結束的時候呼叫fsync或者fdatasync來flush資料到持久裝置去。而且通常是以頁面為單位,16K一次或者4K一次。 安全性保證了,但是效能就有很大的損害。而且我們更新

系統技術業餘研究 » Linux方便的socket讀寫檢視器(socktop)

晚上 雕樑 說要找個工具來調查下unix域套接字的傳送和接受情況,比如說A程式是否送出,B程式是否接收到,他找了tcpdump ,wireshark什麼的,貌似都不支援。 這時候還是偉大的systemtap來救助了。 因為所有的socket通訊都是通過socket介面來的,任何family的通訊

系統技術業餘研究 » Linux誰在消耗我們的cache

Linux下對檔案的訪問和裝置的訪問通常會被cache起來加快訪問速度,這個是系統的預設行為。 而cache需要耗費我們的記憶體,雖然這個記憶體最後可以通過echo 3>/proc/sys/vm/drop_caches這樣的命令來主動釋放。但是有時候我們還是需要理解誰消耗了我們的記憶體。 我

系統技術業餘研究 » Linux誰在切換我們的程序

我們在做Linux伺服器的時候經常會需要知道誰在做程序切換,什麼原因需要做程序切換。 因為程序切換的代價很高,我給出一個LMbench測試出來的數字: Context switching – times in microseconds – smaller is better ———————————

系統技術業餘研究 » Linuxpstack的實現

Linux下有時候我們需要知道一個程序在做什麼,比如說程式不正常的時候,他到底在幹嗎?最直接的方法就是打印出他所有執行緒的呼叫棧,這樣我們從棧再配合程式程式碼就知道程式在幹嗎了。 Linux下這個工具叫做pstack. 使用方法是 # pstack Usage: pstack <proce

系統技術業餘研究 » Linux試驗大頁面對映(MAP_HUGETLB)

Linux對大頁面記憶體的引入對減少TLB的失效效果不錯,特別是記憶體大而密集型的程式,比如說在資料庫中的使用。innodb引擎就支援大頁面記憶體,具體使用可參見 這裡。 大頁面更詳細的資料可以參考: Documentation/vm/hugetlbpage.txt 過去使用大頁面記憶體主要透過h

系統技術業餘研究 » LinuxFio和Blktrace模擬塊裝置的訪問模式

我們在做塊裝置調優的時候, 我們關心的是塊裝置是如何被訪問的,也就是訪問模式(比如說每次從什麼地方讀,每次讀多少塊,熱點在哪裡等),至於每次讀寫的什麼資料我們並不關心. 這些模式當然可以自己去構造,但是如果能把真實應用的訪問模式記錄下來,並且在調優的時候能重放,我們就可以一遍又一遍的除錯直到達到最

系統技術業餘研究 » Linux方便的塊裝置檢視工具lsblk

之前在Linux下看有什麼塊裝置,通常都用fdisk什麼的或者直接ls /dev/ 人肉去看看, 很土,不方便。 前二天在江楓的網站上看到了介紹的lsblk,這玩意不錯,推薦給大家。 這個工具屬於util-linux-ng包,在RHEL 6.1上是安裝好的啦,直接用就好。 ubuntu高版本下也有

系統技術業餘研究 » Linuxpipe使用注意事項

Linux下的pipe使用非常廣泛, shell本身就大量用pipe來粘合生產者和消費者的. 我們的伺服器程式通常會用pipe來做執行緒間的ipc通訊. 由於unix下的任何東西都是檔案,只要是檔案,在讀取的時候,,就會設定last access time, 所以pipe也不例外., 但是這個時間

系統技術業餘研究 » Linux如何知道檔案被那個程序寫

晚上朔海同學問: 一個檔案正在被程序寫 我想檢視這個程序 檔案一直在增大 找不到誰在寫 使用lsof也沒找到 這個問題挺有普遍性的,解決方法應該很多,這裡我給大家提個比較直觀的方法。 linux下每個檔案都會在某個塊裝置上存放,當然也都有相應的inode, 那麼透過vfs.write我們就可以知道

系統技術業餘研究 » Linux檔案預讀分析以及評估對系統的影響

Linux系統很重要的一個性能提升點就是它的Pagecache, 因為記憶體比IO快太多了,所以大家都想進辦法來利用這個cache。 檔案系統也不例外,為了達到高效能,檔案讀取通常採用預讀來預測使用者的行為,把使用者可能需要的資料預先讀取到cache去,達到高效能的目的。 Linux各個發行版re

系統技術業餘研究 » Linux快取記憶體使用率調查

Linux的快取記憶體pagecache對效能的影響至關重要,但是實際系統中我們的利用率如何呢,特別是具體到每個裝置的利用情況。 從下圖我們可以很清楚的看到: 我們知道IO請求由vfs發起,經過pagecache快取,擋不住的就落實到io裝置去,那麼統計這個利用率就很簡單。 我們只要知道擋不住的

系統技術業餘研究 » Linux系統記憶體相關資訊獲取

大型的伺服器,特別是資料庫伺服器的主要瓶頸主要在記憶體,CPU,以及IO上。CPU是可再生資源,不夠用等等就有了;記憶體和土地一樣是不可再生資源,被佔用了,後續的使用必須等到該資源釋放.而IO也非常依賴於記憶體的使用情況,故記憶體的倒騰效率會大大影響伺服器的效率,那麼瞭解伺服器記憶體的使用情況就非

系統技術業餘研究 » Linux 2.6.38 User

Linux核心裡面自帶非常多的加密模組,這是模組經過調優效能非常高, 而且現在又很多硬體本身支援加密功能,比如intel的CPU支援AES加密指令,那些核心的那幫人知道更好如何利用這些硬體更快的完成加密功能的, 他們寫的這些硬體的驅動在drivers/crypto目錄裡. 所以如果我們能在使用者

系統技術業餘研究 » Linux IO協議棧框圖

這張圖很清晰的把linux IO協議棧的層次給勾出來了,而且內容很與時俱進,特別是SCSI裝置的層次對大家理解sg3這樣的包非常有幫助,強烈推薦大家好好研習! 祝玩得開心! Post Footer automatically generated by wp-posturl plugin fo

系統技術業餘研究 » Linux TASK_IO_ACCOUNTING功能以及如何使用

在過去我們瞭解系統IO的情況大多數是通過iostat來獲取的,這個粒度只能精確到每個裝置。通常我們會想了解每個程序,執行緒層面發起了多少IO,在Linux 2.6.20之前除了用systemtap這樣的工具來實現是沒有其他方法的,因為系統沒有暴露這方面的統計。 disktop per裝置per應用

系統技術業餘研究 » Linux Used記憶體到底哪裡去了?

前幾天 純上 同學問了一個問題: 我ps aux看到的RSS記憶體只有不到30M,但是free看到記憶體卻已經使用了7,8G了,已經開始swap了,請問ps aux的實際實體記憶體統計是不是漏了哪些記憶體沒算?我有什麼辦法確定free中used的記憶體都去哪兒了呢? 這個問題不止一個同學遇到過了

系統技術業餘研究 » Linux常用效能調優工具索引

霸爺您好,麻煩請教個問題,我們最近一個專案上有個奇怪的問題,基於實時linux系統,兩個實時執行緒通過mq_send傳送訊息,A發訊息給B,是非阻塞的訊息佇列,A傳送訊息B進行處理,A傳送訊息後發現mq_send的開銷與B對該訊息的處理時延相關,也就是說B處理的快,那麼A呼叫的mq_send返回

系統技術業餘研究 » 看圖學TCP API以及狀態變遷

client的connect呼叫和server端之間的三根線應該對應著三次握手過程,這裡有一點問題。 client傳送的sync到達應該在server端accpet之前,所以橙色線應該指向accpet前面。 同樣,server端響應ack,sync是在accpet呼叫前的,因此粉色線也應該放在a