效能優化的過程學習
背景
即使熟悉了開發中的各項技術和優化技巧,但在真正的效能優化場景下,自己依舊很難開展優化任務。所以需要總結一些優化方案,方便以後查閱和學習。
如何找到優化目標?
應用效能低,有很多方面的因素,比如業務需求層面、架構設計層面、硬體/軟體層面等。
通常,關注一個硬體資源(比如 CPU),我們主要關注以下基本要素。
利用率: 一般是瞬時值,屬於取樣範圍,用來判斷有沒有峰值,比如 CPU 使用率。
飽和度: 一般指資源是否被合理利用,能否用分擔更多的工作。比如,飽和度過高,新請求在特定 queue 裡排隊;再比如,記憶體利用率過低、CPU 利用率過高,就可以考慮空間換時間。
錯誤資訊: 錯誤一般發生在問題嚴重的情況下,需要特別關注。
聯想資訊: 對引起的原因進行猜測,並用更多的工具驗證猜想,猜測影響因素並不一定是準確的,只是幫助我們分析問題,比如系統響應慢很可能是大量使用了 SWAP 導致的。
CPU
檢視 CPU 使用可以使用 top 命令,尤其注意它的負載(load)和使用率,vmstat 命令也可以看到系統的一些執行狀況。
記憶體
記憶體可以使用 free 命令檢視,尤其關注剩餘記憶體的大小(free)。對於 Linux 系統來說,啟動之後由於各種快取和緩衝區的原因,系統記憶體會被迅速佔滿,所以我們更加關注的是 JVM 的記憶體。
top 命令的 RES 列,顯示的就是程式實際佔用的實體記憶體,這個值通常比 jmap 命令獲取的堆記憶體要大,因為它還包含大量的堆外記憶體空間。
網路
iotop 可以看到佔用網路流量最高的程式;通過 netstat 命令或者 ss 命令,能夠看到當前機器上的網路連線彙總。在一些較底層的優化中,會涉及針對 mtu 的網路優化。
I/O
通過 iostat 命令,可以檢視磁碟 I/O 的使用情況,如果利用率過高,就需要從使用源頭找原因;類似 iftop,iotop 可以檢視佔用 I/O 最多的程式,很容易可以找到優化目標。
其他
lsof 命令可以檢視當前程式所關聯的所有資源;sysctl 命令可以檢視當前系統核心的配置引數; dmesg 命令可以顯示系統級別的一些資訊,比如被作業系統的 oom-killer 殺掉的程式就可以在這裡找到。
參考:
解決
找到了具體的效能瓶頸點,就可以針對性地進行優化。
1.CPU 問題
CPU 是系統的核心資源,如果 CPU 有瓶頸,很多工和執行緒就獲取不到時間片,便會執行緩慢。如果此時系統的記憶體充足,就要考慮是否可以空間換時間,通過資料冗餘和更優的演算法來減少 CPU 的使用。
在 Linux 系統上,通過 top-Hp 便能容易地獲取佔用 CPU 最高的執行緒,進行鍼對性的優化。
資源的使用要細分,才能夠進行專項優化。
我曾經碰見一個棘手的效能問題,執行緒都阻塞在 ForkJoin 執行緒池上,經過仔細排查才分析出,程式碼在等待耗時的 I/O 時,採用了並行流(parallelStrea)處理,但是 Java 預設的方式是所有使用並行流的地方,公用了一個通用的執行緒池,這個執行緒池的並行度只有 CPU 的兩倍。所以請求量一增加,任務就會排隊,造成積壓。
2.記憶體問題
記憶體問題通常是 OOM 問題,可以參考“19 | 高階進階:JVM 常見優化引數”進行優化。如果記憶體資源很緊張,CPU 利用率低,則可以考慮時間換空間的方式。
SWAP 分割槽使用硬碟來擴充套件可用記憶體的大小,但它的速度非常慢。一般在高併發的應用中,會把 SWAP 關掉,因為它很容易會引起卡頓。
3.I/O 問題
我們通常開發的業務系統,磁碟 I/O 負載都比較小,但網路 I/O 都比較繁忙。
當遇到磁碟 I/O 佔用高的情況,就要考慮是否是日誌列印得太多導致的。通過調整日誌級別,或者清理無用的日誌程式碼,便可緩解磁碟 I/O 的壓力。
業務系統還會有大量的網路 I/O 操作,比如通過 RPC 呼叫一個遠端的服務,我們期望使用 NIO 來減少一些無效的等待,或者使用並行來加快資訊的獲取。
還有一種情況,是類似於 ES 這樣的資料庫應用,資料寫入本身,就會造成繁重的磁碟 I/O。這個時候,可以增加硬體的配置,比如換成 SSD 磁碟,或者增加新的磁碟。
資料庫服務本身,也會提供非常多的引數,用來調優效能。根據“06 | 案例分析:緩衝區如何讓程式碼加速”和“07 | 案例分析:無處不在的快取,高併發系統的法寶”的描述,這部分的配置引數,主要影響緩衝和快取的行為。
比如 ES 的 segment 塊大小,translog 的重新整理速度等,都可以被微調。舉個例子,大量日誌寫入 ES 的時候,就可以通過增大 translog 寫盤的間隔,來獲得較大的效能提升。
4.網路問題
資料包在網路上傳輸,影響的主要因素就是結果集的大小。通過去除無用的資訊,啟用合理的壓縮,可以獲得較大的效能提升。
值得注意的是,這裡的網路傳輸值得不僅僅是針對瀏覽器的,在服務間呼叫中也有著同樣的情況。
比如,在 SpringBoot 的配置檔案中,通過配置下面的引數,就可以開啟 gzip。
server:
compression:
enabled: true
min-response-size: 1024
mime-types: ["text/html","application/json","application/octet-stream"]
但是,這個 SpringBoot 服務,通過 Feign 介面從另外一個服務獲取資訊,這個結果集並沒有被壓縮。
可以通過替換 Feign 的底層網路工具為 OkHTTP,使用 OkHTTP 的透明壓縮(預設開啟 gzip),即可完成服務間呼叫的資訊壓縮,但很多同學容易忘掉這一環。我曾經調優果一個專案,將返回的資料包從9MB 壓縮到300KB 左右,極大地減少了網路傳輸,節省了大約 500ms 的時間。
網路 I/O 的另外一個問題就是頻繁的網路互動,通過將結果集合並,使用批量的方式,可以顯著增加效能,但這種方式的使用場景有限,比較適合非同步的任務處理。
使用 netstat 命令,或者 lsof 命令,可以獲取程式所關聯的,TIME_WAIT 和 CLOSE_WAIT 網路狀態的數量,前者可以通過調整核心引數來解決,但後者多是應用程式的 BUG。
參考:
以上內容學習自拉勾教育,為方便後續問題排查,簡單記錄下~
相關文章
- Java 效能優化之——效能優化的過程方法與求職面經總結Java優化求職
- Linux效能優化實戰課程教學Linux優化
- 《java學習三》jvm效能優化-------調優JavaJVM優化
- iOS開發過程中 效能監控及優化iOS優化
- SpringIOC初始化過程學習Spring
- 《java學習三》jvm效能優化------jconsulJavaJVM優化
- memcached的學習過程
- Android效能優化相關的學習記錄(1)Android優化
- redis學習(六) 排序(sort,by,store,效能優化)Redis排序優化
- 某知名零售企業ERP系統的效能優化過程優化
- Nginx效能優化(學習筆記二十五)Nginx優化筆記
- 《java學習二》jvm效能優化-----認識jvmJavaJVM優化
- Java學習過程Java
- 瀏覽器輸入URL到 請求全過程以及相應的效能優化瀏覽器優化
- DeepMind用元強化學習框架探索多巴胺在學習過程中的作用強化學習框架
- Oracle優化案例-儲存過程的優化思路(二十三)Oracle優化儲存過程
- Android效能優化之啟動過程(冷啟動和熱啟動)Android優化
- 效能提升 48 倍! python redis 批量寫入大量資料優化過程PythonRedis優化
- Laravel 專案深度優化過程Laravel優化
- Spring 原始碼學習 - 單例bean的例項化過程Spring原始碼單例Bean
- 一次 kafka 消費者的效能調優過程Kafka
- 【前端效能優化】vue效能優化前端優化Vue
- Spark學習——效能調優(一)Spark
- Spark學習——效能調優(二)Spark
- Spark學習——效能調優(三)Spark
- Mysql 5.7儲存過程的學習MySql儲存過程
- Android效能優化——效能優化的難題總結Android優化
- 如何優化產品開發過程?優化
- 效能測試過程中最佳化-3:
- 效能調優學習之硬體調優
- MSP430學習過程
- SQL SERVER 學習過程(一)SQLServer
- 分享一些自己的學習過程和學習方法
- IT學習過程中看懂=學會嗎?
- SEO優化過程中容易發生的誤區優化
- 記canvas畫筆筆跡的多次優化過程Canvas優化
- 詳細說明搜尋引擎優化的過程優化
- Flutter的效能優化Flutter優化