Linux性能優化實戰學習筆記:第三十二講

1、上節總結

專欄更新至今,四大基礎模塊的第三個模塊——文件系統和磁盤 I/O 篇,咱們就已經學完了。很開心你尚未掉隊,仍然在積極學習思考和實踐操做,而且熱情地留言與討論。ios

今天是性能優化的第四期。照例,我從 I/O 模塊的留言中摘出了一些典型問題,做爲今天的答疑內容,集中回覆。一樣的,爲了便於你學習理解,它們並非嚴格按照文章順序排列的。數據庫

每一個問題,我都附上了留言區提問的截屏。若是你須要回顧內容原文,能夠掃描每一個問題右下方的二維碼查看。緩存

2、問題 1:阻塞、非阻塞 I/O 與同步、異步 I/O 的區別和聯繫

一、問題:

二、解答

在文件系統的工做原理篇中,我曾經介紹了阻塞、非阻塞 I/O 以及同步、異步 I/O 的含義,這裏咱們再簡單回顧一下。性能優化

首先咱們來看阻塞和非阻塞 I/O。根據應用程序是否阻塞自身運行,能夠把 I/O 分爲阻塞I/O 和非阻塞 I/O。bash

  • 所謂阻塞 I/O,是指應用程序在執行 I/O 操做後,若是沒有得到響應,就會阻塞當前線程,不能執行其餘任務。
  • 所謂非阻塞 I/O,是指應用程序在執行 I/O 操做後,不會阻塞當前的線程,能夠繼續執行其餘的任務

再來看同步 I/O 和異步 I/O。根據 I/O 響應的通知方式的不一樣,能夠把文件 I/O 分爲同步I/O 和異步 I/O。網絡

  • 所謂同步 I/O,是指收到 I/O 請求後,系統不會馬上響應應用程序;等處處理完成,系統纔會經過系統調用的方式,告訴應用程序 I/O 結果。
  • 所謂異步 I/O,是指收到 I/O 請求後,系統會先告訴應用程序 I/O 請求已經收到,隨後再去異步處理;等處理完成後,系統再經過事件通知的方式,告訴應用程序結果。

你能夠看出,阻塞 / 非阻塞和同步 / 異步,其實就是兩個不一樣角度的 I/O 劃分方式。它們描述的對象也不一樣,阻塞 / 非阻塞針對的是 I/O 調用者(即應用程序),而同步 / 異步針
對的是 I/O 執行者(即系統)。數據結構

我舉個例子來進一步解釋下。好比在 Linux I/O 調用中,多線程

  • 系統調用 read 是同步讀,因此,在沒有獲得磁盤數據前,read 不會響應應用程序。
  • 而 aio_read 是異步讀,系統收到 AIO 讀請求後不等處理就返回了,而具體的 read 結果,再經過回調異步通知應用程序。

再如,在網絡套接字的接口中,異步

  • 使用 send() 直接向套接字發送數據時,若是套接字沒有設置 O_NONBLOCK 標識,那麼 send() 操做就會一直阻塞,當前線程也無法去作其餘事情。
  • 固然,若是你用了 epoll,系統會告訴你這個套接字的狀態,那就能夠用非阻塞的方式使用。當這個套接字不可寫的時候,你能夠去作其餘事情,好比讀寫其餘套接字。

3、問題 2:「文件系統」課後思考

一、問題:

在 文件系統原理 文章的最後,我給你留了一道思考題,那就是執行 find 命令時,會不會致使系統的緩存升高呢?若是會致使,升高的又是哪一種類型的緩存呢?工具

關於這個問題,白華和 coyang 的答案已經很準確了。經過學習 Linux 文件系統的原理,咱們知道,文件名以及文件之間的目錄關係,都放在目錄項緩存中。而這是一個基於內存
的數據結構,會根據須要動態構建。因此,查找文件時,Linux 就會動態構建不在緩存中的目錄項結構,致使 dentry 緩存升高。

 

二、解答

事實上,除了目錄項緩存增長,Buffer 的使用也會增長。若是你用 vmstat 觀察一下,會發現 Buffer 和 Cache 都在增加:

vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  1      0 7563744   6024 225944    0    0  3736     0  574 3249  3  5 89  3  0
 1  0      0 7542792  14736 236856    0    0  8708     0 13494 32335  8 19 66  7  0
 0  1      0 7494452  27280 272284    0    0 12544     0 4550 17084  5 15 68 13  0
 0  1      0 7475084  42380 276320    0    0 15096     0 2541 14253  2  6 78 13  0
 0  1      0 7455728  57600 280436    0    0 15220     0 2025 14518  2  6 70 22  0

這裏,Buffer 的增加是由於,構建目錄項緩存所需的元數據(好比文件名稱、索引節點等),須要從文件系統中讀取。

4、問題 3:「磁盤 I/O 延遲」課後思考

在 磁盤 I/O 延遲案例的最後,我給你留了一道思考題。

咱們經過 iostat ,確認磁盤 I/O 已經出現了性能瓶頸,還用 pidstat 找出了大量磁盤 I/O的進程。可是,隨後使用 strace 跟蹤這個進程,卻找不到任何 write 系統調用。這是爲何呢?

不少同窗的留言都準確回答了這個問題。好比,劃時代和 jeff 的留言都指出,在這個場景中,咱們須要加 -f 選項,以便跟蹤多進程和多線程的系統調用狀況。

你看,僅僅是不恰當的選項,均可能會致使性能工具「犯錯」,呈現這種看起來不合邏輯的結果。很是高興看到,這麼多同窗已經掌握了性能工具使用的核心思路——弄清楚工具
自己的原理和問題。

5、問題 4:「MySQL 案例」課後思考

一、問題

在 MySQL 案例的最後,我給你留了一個思考題。
爲何 DataService 應用中止後,即便仍沒有索引,MySQL 的查詢速度仍是快了不少,而且磁盤 I/O 瓶頸也消失了呢?

 二、解答

ninuxer 的留言基本解釋了這個問題,不過還不夠完善。
事實上,當你看到 DataService 在修改 /proc/sys/vm/drop_caches 時,就應該想到前面學過的 Cache 的做用。
咱們知道,案例應用訪問的數據表,基於 MyISAM 引擎,而 MyISAM 的一個特色,就是隻在內存中緩存索引,並不緩存數據。因此,在查詢語句沒法使用索引時,就須要數據表
從數據庫文件讀入內存,而後再進行處理。

因此,若是你用 vmstat 工具,觀察緩存和 I/O 的變化趨勢,就會發現下面這樣的結果:

vmstat 1

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

# 備註: DataService 正在運行
0  1      0 7293416    132 366704    0    0 32516    12   36  546  1  3 49 48  0
 0  1      0 7260772    132 399256    0    0 32640     0   37  463  1  1 49 48  0
 0  1      0 7228088    132 432088    0    0 32640     0   30  477  0  1 49 49  0
 0  0      0 7306560    132 353084    0    0 20572     4   90  574  1  4 69 27  0
 0  2      0 7282300    132 368536    0    0 15468     0   32  304  0  0 79 20  0

# 備註:DataService 從這裏開始中止
 0  0      0 7241852   1360 424164    0    0   864   320  133 1266  1  1 94  5  0
 0  1      0 7228956   1368 437400    0    0 13328     0   45  366  0  0 83 17  0
 0  1      0 7196320   1368 470148    0    0 32640     0   33  413  1  1 50 49  0
...
 0  0      0 6747540   1368 918576    0    0 29056     0   42  568  0  0 56 44  0
 0  0      0 6747540   1368 918576    0    0     0     0   40  141  1  0 100  0  0

在 DataService 中止前,cache 會連續增加三次後再降回去,這正是由於 DataService 每隔 3 秒清理一次頁緩存。而 DataService 中止後,cache 就會不停地增加,直到增加爲
918576 後,就再也不變了。

這時,磁盤的讀(bi)下降到 0,同時,iowait(wa)也下降到 0,這說明,此時的全部數據都已經在系統的緩存中了。咱們知道,緩存是內存的一部分,它的訪問速度比磁盤快
得多,這也就能解釋,爲何 MySQL 的查詢速度變快了不少。

從這個案例,你會發現,MySQL 的 MyISAM 引擎,自己並不緩存數據,而要依賴系統緩存來加速磁盤 I/O 的訪問。一旦系統中還有其餘應用同時運行,MyISAM 引擎就很難充分
利用系統緩存。由於系統緩存可能被其餘應用程序佔用,甚至直接被清理掉。

因此,通常來講,我並不建議,把應用程序的性能優化徹底創建在系統緩存上。仍是那句話,最好能在應用程序的內部分配內存,構建徹底自主控制的緩存,好比 MySQL 的
InnoDB 引擎,就同時緩存了索引和數據;或者,可使用第三方的緩存應用,好比Memcached、Redis 等。

今天主要回答這些問題,同時也歡迎你繼續在留言區寫下疑問和感想,我會持續不斷地解答。但願藉助每一次的答疑,能夠和你一塊兒,把文章知識內化爲你的能力,咱們不只在實

相關文章
相關標籤/搜索