鯤鵬性能優化十板斧(二)——CPU與內存子系統性能調優


1.1 CPU與內存子系統性能調優簡介

調優思路

性能優化的思路如下:

      l   如果CPU的利用率不高,說明資源沒有充分利用,可以通過工具(如strace)查看應用程序阻塞在哪里,一般為磁盤,網絡或應用程序的業務處理中存在休眠或信號等待,這些優化措施在后續其它章節描述。

      l   如果CPU利用率高,通過優化軟件硬件的配置參數來更好適配業務場景,減少CPU占用率,讓整個系統有更多的CPU時間來處理業務。

我們也可以選擇更好的硬件,根據CPU的能力配置合適的內存條,建議內存滿通道配置,發揮內存最大帶寬:一顆鯤鵬920處理器的內存通道數為8,兩顆鯤鵬920處理器的內存通道數為16;建議選擇高頻率的內存條,提升內存帶寬:鯤鵬920在1DPC配置時,支持的內存最高頻率為2933MHz。

主要優化參數

優化項

優化項簡介

默認值

生效范圍

鯤鵬916

鯤鵬920

優化應用程序的NUMA配置

在NUMA架構下,CPU core訪問臨近的內存時訪問延遲更低。將應用程序綁在一個NUMA節點,可減少因訪問遠端內存帶來的性能下降。

默認不綁定核

立即生效

yes

yes

修改CPU預取開關

內存預取在數據集中場景下可以提前將要訪問的數據讀到CPU cache 中,提升性能;若數據不集中,導致預取命中率低,則浪費內存帶寬。

on

重啟生效

no

yes

調整定時器機制

nohz機制可減少不必要的時鍾中斷,減少CPU調度開銷。

不同OS默認配置不同

Euler:nohz=off

重啟生效

yes

yes

調整內存的頁大小為64K

內存的頁大小越大,TLB中每行管理的內存越多,TLB命中率就越高,從而減少內存訪問次數。

不同OS默認配置不同:

4KB或64K

重新編譯內核、更新內核后生效

yes

yes

優化應用程序的線程並發數

適當調整應用的線程並發數,使得充分利用多核能力和資源爭搶之間達到平衡。

由應用本身決定

立即生效或重啟生效(由應用決定)

yes

yes

1.2 常用性能監測工具

1.2.1 top工具

介紹

top是最常用的Linux性能監測工具之一。通過top工具可以監視進程和系統整體性能。

命令參考舉例:

命令

說明

top

查看系統整體的CPU、內存資源消耗。

top執行后輸入1

查看每個CPU core資源使用情況。

top執行后輸入F,並選擇P選項

查看線程執行過程中是否調度到其它CPU core。

top -p $PID -H

查看某個進程內所有線程的CPU資源占用。

安裝方式

系統自帶,無需安裝。

使用方法

                                步驟 1      使用top命令統計整體CPU、內存資源消耗。

l   CPU項:顯示當前總的CPU時間使用分布。

  • us表示用戶態程序占用的CPU時間百分比。

  • sy表示內核態程序所占用的CPU時間百分比。

  • wa表示等待IO等待占用的CPU時間百分比。

  • hi表示硬中斷所占用的CPU時間百分比。

  • si表示軟中斷所占用的CPU時間百分比。

通過這些參數我們可以分析CPU時間的分布,是否有較多的IO等待。在執行完調優步驟后,我們也可以對CPU使用時間進行前后對比。如果在運行相同程序、業務情況下CPU使用時間降低,說明性能有提升。

l   KiB Mem:表示服務器的總內存大小以及使用情況。

l   KiB Swap:表示當前所使用的Swap空間的大小。Swap空間即當內存不足的時候,把一部分硬盤空間虛擬成內存使用。如果當前所使用的Swap空間大於0,可以考慮優化應用的內存占用或增加物理內存。

                                步驟 2      在top命令執行后按1,查看每個CPU core的使用情況。

通過該命令可以查看單個CPU core的使用情況,如果CPU占用集中在某幾個CPU core上,可以結合業務分析觸發原因,從而找到優化思路。

    步驟 3      選中top命令的P選項,查看線程運行在哪些 CPU core上。

在top命令執行后按F,可以進入top命令管理界面。在該界面通過上下鍵移動光標到P選項,通過空格鍵選中后按Esc退出,即可顯示出線程運行的CPU核。觀察一段時間,若業務線程在不同NUMA節點內的CPU core上運行,則說明存在較多的跨NUMA訪問,可通過NUMA綁核進行優化。

 步驟 4      使用top -p $PID -H命令觀察進程中每個線程的CPU資源使用。

“-p”后接的參數為待觀察的進程ID。通過該命令可以找出消耗資源多的線程,隨后可根據線程號分析線程中的熱點函數、調用過程等情況

----結束

1.2.2 Perf工具

介紹

Perf工具是非常強大的Linux性能分析工具,可以通過該工具獲得進程內的調用情況、資源消耗情況並查找分析熱點函數。

命令參考舉例:

命令

說明

perf top

查看當前系統中的熱點函數。

perf sched record -- sleep 1 -p $PID

記錄進程在1s內的系統調用。

perf sched latency --sort max

查看上一步記錄的結果,以調度延遲排序。

安裝方式

以CentOS為例,使用如下命令安裝:

# yum -y install perf

使用方法

                                步驟 1      通過perf top命令查找熱點函數。

該命令統計各個函數在某個性能事件上的熱度,默認顯示CPU占用率,可以通過“-e”監控其它事件。

l   Overhead表示當前事件在全部事件中占的比例。

l   Shared Object表示當前事件生產者,如kernel、perf命令、C語言庫函數等。

l   Symbol則表示熱點事件對應的函數名稱。

通過熱點函數,我們可以找到消耗資源較多的行為,從而有針對性的進行優化。

 步驟 2      收集一段時間內的線程調用。

perf sched record命令用於記錄一段時間內,進程的調用情況。“-p”后接進程號,“sleep”后接統計時長,單位為秒。收集到的信息自動存放在當前目錄下,文件名為perf.data。

   步驟 3      解析收集到的線程調度信息。

perf sched latency命令可以解析當前目錄下的perf.data文件。“-s”表示進行排序,后接參數“max”表示按照最大延遲時間大小排序。

----結束

1.2.3 numactl工具

介紹

numactl工具可用於查看當前服務器的NUMA節點配置、狀態,可通過該工具將進程綁定到指定CPU core,由指定CPU core來運行對應進程。

命令參考舉例:

命令

說明

numactl -H

查看當前服務器的NUMA配置。

numactl -C 0-7 ./test

將應用程序test綁定到0~7核運行。

numastat

查看當前的NUMA運行狀態。

安裝方式

以CentOS為例,使用如下命令安裝:

# yum -y install numactl numastat

使用方法

                                步驟 1      通過numactl查看當前服務器的NUMA配置。

從numactl執行結果可以看到,示例服務器共划分為4個NUMA節點。每個節點包含16個CPU core,每個節點的內存大小約為64GB。同時,該命令還給出了不同節點間的距離,距離越遠,跨NUMA內存訪問的延時越大。應用程序運行時應減少跨NUMA訪問內存。

步驟 2      通過numactl將進程綁定到指定CPU core。

通過 numactl -C 0-15 top 命令即是將進程“top”綁定到0~15 CPU core上執行。

可以通過numastat命令觀察各個NUMA節點的狀態。

l   numa_hit表示節點內CPU核訪問本地內存的次數。

l   numa_miss表示節點內核訪問其他節點內存的次數。跨節點的內存訪問會存在高延遲從而降低性能,因此,numa_miss的值應當越低越好,如果過高,則應當考慮綁核。

----結束

1.3 優化方法

1.3.1 NUMA優化,減少跨NUMA訪問內存

原理

通過1.1 鯤鵬處理器NUMA簡介章節可以看到不同NUMA內的CPU core訪問同一個位置的內存,性能不同。內存訪問延時從高到低為:跨CPU > 跨NUMA不跨CPU > NUMA內

因此在應用程序運行時要盡可能的避免跨NUMA訪問內存,我們可以通過設置線程的CPU親和性來實現。

修改方式

l   網絡可以通過如下方式綁定運行的CPU core,其中$cpuMask是16進制的數,最右邊的bit表示core0;$irq為網卡隊列中斷號。

echo $cpuMask > /proc/irq/$irq/smp_affinity_list

l   通過numactl啟動程序,如下面的啟動命令表示啟動test程序,只能在CPU core 28到core31運行(-C控制)。

numactl -C 28-31 ./test

l   在C/C++代碼中通過sched_setaffinity函數來設置線程親和性。

l   很多開源軟件已經支持在自帶的配置文件中修改線程的親和性,例如nginx可以修改nginx.conf文件中的worker_cpu_affinity參數來設置nginx線程親和性。

1.3.2 修改CPU的預取開關

原理

局部性原理分為時間局部性原理和空間局部性原理:

l   時間局部性原理(temporal locality):如果某個數據項被訪問,那么在不久的將來它可能再次被訪問。

l   空間局部性原理(spatial locality):如果某個數據項被訪問,那么與其地址相鄰的數據項可能很快也會被訪問。

CPU將內存中的數據讀到CPU的高速緩沖Cache時,會根據局部性原理,除了讀取本次要訪問的數據,還會預取本次數據的周邊數據到Cache里面,如果預取的數據是下次要訪問的數據,那么性能會提升,如果預取的數據不是下次要取的數據,那么會浪費內存帶寬。

對於數據比較集中的場景,預取的命中率高,適合打開CPU預取,反之需要關閉CPU預取。目前發現speccpu和X265軟件場景適合打開CPU預取,STREAM測試工具、Nginx和數據庫場景需要關閉CPU預取。

修改方式

按照B 進入BIOS界面的步驟進入BIOS,然后在BIOS的如下位置設置CPU的預取開關。

1.3.3 定時器機制調整,減少不必要的時鍾中斷

原理

在Linux內核2.6.17版本之前,Linux內核為每個CPU設置一個周期性的時鍾中斷,Linux內核利用這個中斷處理一些定時任務,如線程調度等。這樣導致就算CPU不需要定時器的時候,也會有很多時鍾中斷,導致資源的浪費。Linux 內核2.6.17版本引入了nohz機制,實際就是讓時鍾中斷的時間可編程,減少不必要的時鍾中斷。

修改方式

執行cat /proc/cmdline查看Linux 內核的啟動參數,如果有nohz=off關鍵字,說明nohz機制被關閉,需要打開。修改方法如下:

image.png

修改前后,可以通過如下命令觀察timer_tick的調度次數,其中$PID為要觀察的進程ID,可以選擇CPU占用高的進程進行觀察:

perf sched record -- sleep 1 -p $PID

perf sched latency -s max

輸出信息中有如下信息,其中591字段表示統計時間內的調度次數,數字變小說明修改生效。

timer_tick:(97) | 7.364 ms | 591 | avg: 0.012 ms | max: 1.268 ms

                                步驟 1      在“/boot”目錄下通過find -name grub.cfg找到啟動參數的配置文件。

                                步驟 2      在配置文件中將nohz=off去掉。

                                步驟 3      重啟服務器。

----結束

1.3.4 調整內存頁的大小為64K,提升TLB命中率

原理

TLB(Translation lookaside buffer)為頁表(存放虛擬地址的頁地址和物理地址的頁地址的映射關系)在CPU內部的高速緩存。TLB的命中率越高,頁表查詢性能就越好。

TLB的一行為一個頁的映射關系,也就是管理了一個頁大小的內存:

TLB管理的內存大小 = TLB行數 x 內存的頁大小

同一個CPU的TLB行數固定,因此內存頁越大,管理的內存越大,相同業務場景下的TLB命中率就越高。

修改方式

修改Linux內核編譯選項,並重新編譯:

image.png

修改前后可以通過如下命令觀察TLB的命中率($PID為進程ID):

perf stat -p $PID -d -d -d

輸出結果包含如下信息,其中1.21%和0.59%分別表示數據的miss率和指令的miss率。

1,090,788,717      dTLB-loads                #  520.592 M/sec
13,213,603      dTLB-load-misses          #    1.21% of all dTLB cache hits
669,485,765      iTLB-loads                #  319.520 M/sec
3,979,246      iTLB-load-misses          #    0.59% of all iTLB cache hits

                                步驟 1      執行make menuconfig。

                                步驟 2      選擇PAGESIZE大小為64K。

Kernel Features-->Page size(64KB)

                                步驟 3      編譯和安裝內核。

參考https://bbs.huaweicloud.com/forum/thread-24362-1-1.html

----結束

1.3.5 調整線程並發數

原理

程序從單線程變為多線程時,CPU和內存資源得到充分利用,性能得到提升。但是系統的性能並不會隨着線程數的增長而線性提升,因為隨着線程數量的增加,線程之間的調度、上下文切換、關鍵資源和鎖的競爭也會帶來很大開銷。當資源的爭搶比較嚴重時,甚至會導致性能明顯降。下面數據為某業務場景下,不同並發線程數下的TPS,可以看到並發線程數達到128后,性能達到高峰,隨后開始下降。我們需要針對不同的業務模型和使用場景做多組測試,找到適合本業務場景的最佳並發線程數。

修改方式

不同的軟件有不同的配置,需要根據代碼實現來修改,這里舉例幾個常用開源軟件的修改方法:

  • MySql可以通過innodb_thread_concurrency設置工作線程的最大並發數。

  • Nginx可以通過worker_processes參數設置並發的進程個數。

作者:萊德汪汪隊

 

 

 

 

 


免責聲明!

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



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