linux性能調優總結


系統性能一直是個熱門話題。做運維這幾年也一直在搞性能調優,寫這個文章也算是對工作的總結。

講調優第一步是,要講為什么要調優?也就是系統分析,分析還需要有指標,做好性能監控的情況下,看到確實需要調優才能進行。不能為了調優而 “調優“ 那不是調優,那是破壞。

性能分析的目的

  1. 找出系統性能瓶頸
  2. 為以后的優化提供方案或者參考
  3. 達到良好利用資源的目的。硬件資源和軟件配置。

影響性能的因素

想確定有哪些因素,首先確定你的應用是什么類型的?
例如:

  1. cpu密集型
    例如web服務器像nginx node.js需要CPU進行批處理和數學計算都屬於此類型
  2. io密集型
    例如數據庫常見的mysql,大量消耗內存和存儲系統,對CPU和網絡要求不高,這種應用使用CPU來發起IO請求,然后進入sleep狀態。

確定了應用類型就開始分析有哪些情況能影響性能:

  1. 大量的網頁請求會填滿運行隊列、大量的上下文切換,中斷
  2. 大量的磁盤些請求
  3. 網卡大量的吞吐
  4. 以及內存耗盡等。。

歸結起來就是4個方面

  1. cpu
  2. memory
  3. i/o
  4. network

系統檢測的工具

我們知道了這四大塊影響着我們的性能,那我們有什么工具進行檢測呢?

系統調優.png-341.3kB

上圖時某國外大神總結的。

我個人在工作中常用到的有:
htop vmstat iotop sar strace iftop ss lsof ethtool mtr等

另外推薦阿里的tsar以及glances進行系統性能監控。

CPU 性能監控以及調優

我們可以 通過檢查cpu使用量,通過工具觀測上下文切換、中斷以及代碼調用等方面來進行優化。

首先明確幾個術語:
緩存:為了提供內存i/o性能cpu提供硬件級緩存。查看緩存可以用過 lscpu -p命令來查看

# lscpu 
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              8192K

1級緩存為靜態緩存,分為數據緩存和指令緩存。
2級和3級緩存為動態緩存,其中2級緩存為共享緩存。

為了提高cpu緩存命中率我們通常的做法是把cpu綁定在某一個核上,也就是”cpu親和性”
linux下我們可以通過”taskset”命令來實現

# taskset -pc 0 73890
pid 73890's current affinity list: 0
pid 73890's new affinity list: 0

但是這樣還是有問題。例如不能保證本地內存分配,所以這時候我們需要使用numa來解決問題

NUMA:非一致性內存訪問機制。每個屋里核心都有一段自己使用的內存成為本地節點,都有自己的內存控制器,距離最近的內存節點成稱為鄰均節點。

numa.png-21.6kB
上圖為numa的簡單的拓撲,來源於互聯網。

numactl可以將程序綁定到特定的numa節點

# numactl --show #查看當前的numa配置
policy: default
preferred node: current
physcpubind: 0 
cpubind: 0 
nodebind: 0 
membind: 0 

注:數據庫服務器不要用numa,如果要使用請在數據庫啟動請使用numactl —interleave=all。作為運維可能都被坑過。

cpu調度策略

  1. 實時調度策略
    • SCHED_FIFO 靜態調度策略,一旦占用cpu則一直運行,一直運行直到有更高優先級任務到達或自己放棄。
    • SCHED_RR 時間輪詢策略,當進程的時間片用完,系統將重新分配時間片,並置於就緒隊列尾。放在隊列尾保證了所有具有相同優先級的RR任務的調度公平。
      實時調度策略作用值為1-99,數字越大優先級越高。
  2. 一般策略
    • SCHED_OTHER 默認調度策略通過nice和counter值決定權值,nice越小,counter越大,被調度的概率越大,也就是曾經使用了cpu最少的進程將會得到優先調度。作用值為100-139,數字越小優先級越高。
    • SCHED_BATCH
    • SCHED_IDLE

chrt 修改實時優先級,生產中一般不要修改,默認是rr調度

SCHED_OTHER 使用nice、renice修改。
另外other支持動態調整,如果手動直接nice修改即可。

context switches:上下文切換

linux內核將每一個core當作一個獨立的處理器。一個內核可以同時運行50~50000個進程。每個線程將會分配一個時間片,直到這個線程的時間片用完,或是被更高優先級的線程搶占,它才會被重新放回cpu隊列。切換線程的過程就是context switch。context switch越高,則內核調度的工作負擔越大。

vmstat 既可以看到 cs的高低

run queue 運行隊列

每個cpu都有一個運行隊列。線程,要么在sleep狀態(阻塞並等待IO),要么在運行狀態。運行隊列越長,則等待cpu處理這個線程的時間越長。運行隊列是全局的會被所有CPU共享

load就是用來描述運行隊列的。它的值等於當前正在處理的線程+運行隊列里面的線程。

比如當前系統核數是2,有兩個線程正在執行行,還有4個線程在運行隊列里面,那么它的load=2+4。

vmstat w uptime 都可以觀測運行隊列負載情況。

cpu性能監控

說了這么多,那正常情況下需要觀察哪些值呢?
首先numa 以及算法都是特殊情況下優化的,一般情況下不會去動這些,需要根據你的業務場景來進行綁定調整,像虛擬化,雲計算等可能就需要進行調整。

那么我們日常需要觀測的性能點是:

  1. cpu利用率
    • us 60%-70%
    • sy 30%-35%
    • id 0%-5%
  2. cs上下文切換
    • cs和cpu利用率相關,如果能保持上面所說的利用率大量的切換可以接受
  3. 運行隊列
    • 小於等於4最好

例子:

# vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 3  0 1150840 271628 260684 5530984    0    0     2     1    0    0 22  4 73  0  0
 5  0 1150840 270264 260684 5531032    0    0     0     0 5873 6085 13 13 73  0  0
 5  0 1150840 263940 260684 5531040    0    0     0     4 6721 7507 15 13 72  0  0
 4  0 1150840 263320 260684 5531068    0    0     0     0 6111 7117 10 13 76  0  0
 4  0 1150840 262328 260684 5531072    0    0     0     0 6854 7673 18 13 68  0  0

例子中cpu中斷(in)以及上下文切換(cs)都比較高,說明內核不得不來回切換進程,同時in也是比較高說明cpu一直在請求資源。

內存memory

術語
MMU:
CPU是不能與硬盤打交道的,只有數據被載入到內存中才可以被CPU調用。cpu在訪問內存的時候需要先像內存監控程序請求,由監控程序控制和分配內存的讀寫請求,這個監控程序叫做MMU(內存管理單元)

線性地址到物理地址的映射,如果按照1個字節1個字節映射的話,需要一張非常大的表,這種轉換關系會非常的復雜。因此把內存空間又划分成了另外一種存儲單元格式,通常為4K。

每個進程如果需要訪問內存的時候都需要去查找page table的話需要借助緩沖器TLB,但每次產找tlb沒有或者大量查找還是會造成緩慢,所以又有了page table的分級目錄。page table可以分為1級目錄,2級目錄和偏移量。

另外讓系統管理大量內存有兩種方法:

  1. 增加硬件內存管理單元中頁表數
  2. 增大頁面大小
    第一種方法不太現實,所有我們考慮第二種方法。即:大頁面。
    32位系統4m大頁框64位系統2m大頁框,頁框越粗浪費越嚴重。
    查看系統的大頁面:

    cat /proc/meminfo

    AnonHugePages: 309248 kB
    HugePages_Total: 0
    HugePages_Free: 0
    HugePages_Rsvd: 0
    HugePages_Surp: 0
    Hugepagesize: 2048 kB
    DirectMap4k: 6144 kB
    DirectMap2M: 1042432 kB
    DirectMap1G: 0 kB
    AnonHugePages:透明大頁面,THP是一個提取層,可自動創建、管理和使用超大頁面的大多數方面。
    另外HP必須在引導時設置。
    手動設置大頁面的頁數:
    sysctl vm.nr_hugepages = 20

DMA:直接讀取內存
在實現DMA傳輸時,是由DMA控制器直接掌管總線,因此,存在着一個總線控制權轉移問題。即DMA傳輸前,CPU要把總線控制權交給DMA控制器,而在結束DMA傳輸后,DMA控制器應立即把總線控制權再交回給CPU。一個完整的DMA傳輸過程必須經過DMA請求、DMA響應、DMA傳輸、DMA結束4個步驟。

虛擬內存:
32位的系統上每一個進程在訪問內存的時候,每一個進程都當做自己有4個G的內存空間可用,這叫虛擬內存(地址),虛擬內存轉化成物理內存是通過MMU來完成的。生產中我們盡量不使用虛擬內存。

影響系統性能的幾個內存參數:

  1. overcommit_memory 過量使用內存
    • 0 默認設置系統決定是否過量使用。
    • 1 不過量使用
    • 2 過量使用但有一定的比例默認百分值五十由overcommit_ratio決定(他就是默認的50),舉個例子物理內存8g,swap4g,可以過量使用10g。
      注:生產中盡量避免過量使用,例如redis要關閉過量使用。
  2. spappines
    -將不活躍的進程換進swap。注:盡量不去使用swap。
    生產中設置:
    echp 10 > /proc/sys/vm/swappines
  3. 回收內存
    • 這個值設定為 1、2 或者 3 讓內核放棄各種頁緩存和 slab 緩存的各種組合。
      1 系統無效並釋放所有頁緩沖內存即buffers
      2 系統釋放所有未使用的 slab 緩沖內存。即cached
      3 系統釋放所有頁緩沖和 slab 緩沖內存。
      生產中使用:
      1.運行sync
    1. echo 3>/proc/sys/vm/drop_caches

i/o

IO子系統一般是linux系統中最慢的部分。一個原因是它距離CPU的距離,另一個原因是它的物理結構。因此盡量要減少磁盤IO。

磁盤調度策略:

# cat /sys/block/sda/queue/scheduler 
noop anticipatory deadline [cfq] 

其中當前使用cfq策略。
cfq:完全公平調度。在其時間片段中,進程每次最多可有八個請求(默
認)。調度程序會嘗試根據歷史數據估計某個程序是否會在近期發出更多 I/O,然后 CFQ 會閑置,等待那個
I/O,即使有其他進程正在等待發出 I/O
deadline:每一個請求在指定的期限前必須得到服務。
noop:沒有策略
anticipatory:已被拋棄,寫多讀少的場景使用。

linux內核以page為單位訪問磁盤IO,一般為4K。
查看page: /usr/bin/time -v date

MPF
linux會將內存物理地址空間映射到虛擬內存,內核僅會映射需要的內存頁。當應用啟動時,內核依次搜索CPU cache和物理內存,查找是否有相應的內存頁,如果不存在,則內核將會發起一次MPF(major page fault),將磁盤中的數據讀出並緩存到內存中。

如果在buffer cache找到了對應的內存頁,則將會產生一個MnPF(minor page fault).

/usr/bin/time -v helloworld
第一次執行會發現大部分是MPF
第二次執行會發現大部分是MnPF

The File Buffer Cache

file buffer cache用來減少MPF,增加MnPF,它將會持續增長,直到可用內存比較少或是內核需要為其它應用來釋放一些內存。free內存比較少,並不能說明系統內存緊張,只能說明linux系統充分使用內存來做cache.

# cat /proc/meminfo 
MemTotal:        1004772 kB
MemFree:           79104 kB
Buffers:          105712 kB

將數據頁寫回磁盤
可以使用fsync()或是sync()立即寫回,如果沒有直接調用這些函數,pdflush會定期刷回磁盤。

iotop可以顯示所有進程的IO占用情況
lsof可以查看所有的調用並打開的文件

其他命令:
vmstat sar iostat top htop等


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM