Linux性能優化

導言:在linux系統中檢查指標和影響性能的主要分爲以下四個大塊:
1、CPU
2、內存
3、文件系統和I/O模塊
4、網絡

一、CPU

1、CPU的性能指標主要由:CPU使用率、上下文切換、平均負載、CPU緩存命中率所影響。
2、檢查工具:top(可現實內存使用情況,CPU使用率)、pidstat(可查看每個進程的CPU使用率)、ps(查看進程的運行端口等信息),uptime(用來查看1min,5min,15min的平均負載------這裏的平均負載應注意不單單指的是cpu還包括I/O的情況。)
3、進程的狀態:
S:可中斷睡眠狀態
R:運行狀態
Z:殭屍狀態
T:中斷狀態
D:不可中斷狀態(讀取磁盤的時候)
4、系統壓力測試工具:stress(模擬進程),sysbench(模擬線程)
5、CPU的上下文切換:主要分爲3種(上下文的切換涉及到系統調用,耗費系統的性能)
(1)進程上下文切換:不同進程之間的切換,進程的切換涉及到棧、堆等信息的保存
(2)線程上下文切換:進程的調度和管理是由內核來管理的,而其中所管理的單位就是線程,進程知識給每個線程提供了虛擬內存、全局變量等信息。線程切換也要保存臨時信息
(3)中斷上下文切換:比如磁盤請求等,中斷指的是當前系統運行某個請求,這時候有另外一個請求來了,系統必須通知該請求。

6、軟中斷和硬中斷

硬中斷:外部硬件設備、磁盤、鍵盤燈中斷
軟中斷:由軟件、程序內的定時器、RCU鎖、網路請求分發(軟硬中斷均有)

7、 一般的檢查流程:
<1> top 查看iostat,看是I/O引起的還是CPU引起的
在這裏插入圖片描述
<2>pidstat 查看是哪個程序所引起的,查看哪個程序的CPU使用率比較高

在這裏插入圖片描述
<3>strace追蹤程序調用棧查看是那一部分出現的問題。
在這裏插入圖片描述

<4>如果是中斷引起的,還可以查看proc文件夾下的(這個文件夾主要保存着用戶和內核的交互文件)

2、內存

1、內存的性能指標:系統內存指標、進程內存指標、swap
2、linux通常是通過內存映射來管理內存的

在這裏插入圖片描述
通常真正的物理內存不是很大,所以通過虛擬內存的方式,將磁盤的地址映射到物理地址的某一段空間。
3、虛擬內存的空間通常由以下幾個部分組成

在這裏插入圖片描述
其中的堆和文件映射時動態分配,其他都是靜態分配,比如數據段和只讀段、棧在運行時自動創建,而堆和文件映射可由用戶進行配置。
4、在出現內存緊張的時候,系統會進行一系列的機制來進行內存回收

<1>回收緩存(LRU算法)
<2>回收不常訪問的內存,把不常用的內存通過交換分區換到磁盤上面(swap分區),注意這裏是整個進行,而頁面置換算法只是置換進程的某一部分。
<3>殺死進程,< OOM >,直接殺掉佔用大量內存的進程

5、
(1)常用命令:free(查看總的內存情況,使用情況,空閒情況,緩存情況)
在這裏插入圖片描述

其中要區分buffer和cache,一個是磁盤的緩存,一個是文件系統的緩存,通常爲了給用戶更好的使用,操作系統會提供文件系統,通過文件系統在到磁盤,但是也有可能存在直接I/O的。

(2)用top查看進程的內存使用情況

在這裏插入圖片描述(3)vmstat
在這裏插入圖片描述

3、文件系統和I/O模塊

1、每個文件系統都爲文件分配兩個數據結構,一個是索引節點(inode)和目錄項
(1)索引節點:索引節點,簡稱爲inode,用來記錄文件的元數據,比如inode編號、文件大小、訪問權限、修改日期、數據的位置等。索引節點和文件一一對應,它跟文件內容一樣,都會被持久化存儲到磁盤中。所以記住,索引節點同樣佔用磁盤空間。
(2)目錄項,簡稱爲dentry,用來記錄文件的名字、索引節點指針以及與其他目錄項的關聯關係。多個關聯的目錄項,就構成了文件系統的目錄結構。不過,不同於索引節點,目錄項是由內核維護的一個內存數據結構,所以通常也被叫做目錄項緩存。
換句話說,索引節點是每個文件的唯一標誌,而目錄項維護的正是文件系統的樹狀結構。目錄項和索引節點的關係是多對一,你可以簡單理解爲,一個文件可以有多個別名。

其中組織形式如圖:
在這裏插入圖片描述
2、虛擬文件系統
目錄項、索引節點、邏輯塊以及超級塊,構成了Linux文件系統的四大基本要素。

第一,目錄項本身就是一個內存緩存,而索引節點則是存儲在磁盤中的數據。在前面的Buffer和Cache原理中,我曾經提到過,爲了協調慢速磁盤與快速CPU的性能差異,文件內容會緩存到頁緩存Cache中。

那麼,你應該想到,這些索引節點自然也會緩存到內存中,加速文件的訪問。

第二,磁盤在執行文件系統格式化時,會被分成三個存儲區域,超級塊、索引節點區和數據塊區。其中,

超級塊,存儲整個文件系統的狀態。

索引節點區,用來存儲索引節點。

數據塊區,則用來存儲文件數據。

不過,爲了支持各種不同的文件系統,Linux內核在用戶進程和文件系統的中間,又引入了一個抽象層,也就是虛擬文件系統VFS(Virtual File System)。
VFS 定義了一組所有文件系統都支持的數據結構和標準接口。這樣,用戶進程和內核中的其他子系統,只需要跟VFS 提供的統一接口進行交互就可以了,而不需要再關心底層各種文件系統的實現細節。

這裏,我畫了一張Linux文件系統的架構圖,幫你更好地理解系統調用、VFS、緩存、文件系統以及塊存儲之間的關係。
在這裏插入圖片描述通過這張圖,你可以看到,在VFS的下方,Linux支持各種各樣的文件系統,如Ext4、XFS、NFS等等。按照存儲位置的不同,這些文件系統可以分爲三類。

第一類是基於磁盤的文件系統,也就是把數據直接存儲在計算機本地掛載的磁盤中。常見的Ext4、XFS、OverlayFS等,都是這類文件系統。

第二類是基於內存的文件系統,也就是我們常說的虛擬文件系統。這類文件系統,不需要任何磁盤分配存儲空間,但會佔用內存。我們經常用到的 /proc 文件系統,其實就是一種最常見的虛擬文件系統。此外,/sys 文件系統也屬於這一類,主要向用戶空間導出層次化的內核對象。

第三類是網絡文件系統,也就是用來訪問其他計算機數據的文件系統,比如NFS、SMB、iSCSI等。

這些文件系統,要先掛載到 VFS 目錄樹中的某個子目錄(稱爲掛載點),然後才能訪問其中的文件。拿第一類,也就是基於磁盤的文件系統爲例,在安裝系統時,要先掛載一個根目錄(/),在根目錄下再把其他文件系統(比如其他的磁盤分區、/proc文件系統、/sys文件系統、NFS等)掛載進來。

3、
(1)查看文件系統的磁盤空間情況命令df
在這裏插入圖片描述
(2)sar(系統活動情況報告)
(3)iostat,(讀寫指標,使用情況分析)

在這裏插入圖片描述

4、網絡

(1)OSI網絡模型和TCP/IP模型

在這裏插入圖片描述
(2)IP網絡棧示意圖

在這裏插入圖片描述

(3)一個網絡包的處理過程

在這裏插入圖片描述

網路包的發送接收過程

首先,應用程序調用 Socket API(比如 sendmsg)發送網絡包。

由於這是一個系統調用,所以會陷入到內核態的套接字層中。套接字層會把數據包放到 Socket 發送緩衝區中。

接下來,網絡協議棧從 Socket 發送緩衝區中,取出數據包;再按照 TCP/IP 棧,從上到下逐層處理。比如,傳輸層和網絡層,分別爲其增加 TCP 頭和 IP 頭,執行路由查找確認下一跳的 IP,並按照 MTU 大小進行分片。

分片後的網絡包,再送到網絡接口層,進行物理地址尋址,以找到下一跳的 MAC 地址。然後添加幀頭和幀尾,放到發包隊列中。這一切完成後,會有軟中斷通知驅動程序:發包隊列中有新的網絡幀需要發送。

最後,驅動程序通過 DMA ,從發包隊列中讀出網絡幀,並通過物理網卡把它發送出去。

(5)常用命令ip、ifconfig、netstat、ping

在這裏插入圖片描述

(6)網絡I/O模型優化-------I/O多路複用

水平觸發: 只要文件描述符可以非阻塞地執行 I/O ,就會觸發通知。也就是說,應用程序可以隨時檢查文件描述符的狀態,然後再根據狀態,進行 I/O 操作。

邊緣觸發: 只有在文件描述符的狀態發生改變(也就是 I/O 請求達到)時,才發送一次通知。這時候,應用程序需要儘可能多地執行 I/O,直到無法繼續讀寫,纔可以停止。如果 I/O 沒執行完,或者因爲某種原因沒來得及處理,那麼這次通知也就丟失了。

<1> 第一種,使用非阻塞 I/O 和水平觸發通知,比如使用 select 或者 poll。

根據剛纔水平觸發的原理,select 和 poll 需要從文件描述符列表中,找出哪些可以執行 I/O ,然後進行真正的網絡 I/O 讀寫。由於 I/O 是非阻塞的,一個線程中就可以同時監控一批套接字的文件描述符,這樣就達到了單線程處理多請求的目的。

所以,這種方式的最大優點,是對應用程序比較友好,它的 API 非常簡單。

但是,應用軟件使用 select 和 poll 時,需要對這些文件描述符列表進行輪詢,這樣,請求數多的時候就會比較耗時。並且,select 和 poll 還有一些其他的限制。

select 使用固定長度的位相量,表示文件描述符的集合,因此會有最大描述符數量的限制。比如,在 32 位系統中,默認限制是 1024。並且,在select 內部,檢查套接字狀態是用輪詢的方法,再加上應用軟件使用時的輪詢,就變成了一個 O(n^2) 的關係。

而 poll 改進了 select 的表示方法,換成了一個沒有固定長度的數組,這樣就沒有了最大描述符數量的限制(當然還會受到系統文件描述符限制)。但應用程序在使用 poll 時,同樣需要對文件描述符列表進行輪詢,這樣,處理耗時跟描述符數量就是 O(N) 的關係。

除此之外,應用程序每次調用 select 和 poll 時,還需要把文件描述符的集合,從用戶空間傳入內核空間,由內核修改後,再傳出到用戶空間中。這一來一回的內核空間與用戶空間切換,也增加了處理成本。

有沒有什麼更好的方式來處理呢?答案自然是肯定的。
<2> 使用非阻塞 I/O 和邊緣觸發通知,比如 epoll。

既然 select 和 poll 有那麼多的問題,就需要繼續對其進行優化,而 epoll 就很好地解決了這些問題。

epoll 使用紅黑樹,在內核中管理文件描述符的集合,這樣,就不需要應用程序在每次操作時都傳入、傳出這個集合。

epoll 使用事件驅動的機制,只關注有 I/O 事件發生的文件描述符,不需要輪詢掃描整個集合。

不過要注意,epoll 是在 Linux 2.6 中才新增的功能(2.4 雖然也有,但功能不完善)。由於邊緣觸發只在文件描述符可讀或可寫事件發生時才通知,那麼應用程序就需要儘可能多地執行 I/O,並要處理更多的異常事件。

<3> 使用異步 I/O(Asynchronous I/O,簡稱爲 AIO)。
在前面文件系統原理的內容中,我曾介紹過異步I/O 與同步 I/O 的區別。異步I/O 允許應用程序同時發起很多 I/O 操作,而不用等待這些操作完成。而在 I/O完成後,系統會用事件通知(比如信號或者回調函數)的方式,告訴應用程序。這時,應用程序纔會去查詢 I/O 操作的結果。

參考文獻:極客時間 Linux性能優化實戰 倪朋飛

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章