java获取cpu使用率_2019年阿里P8架构师的解析:最新Java性能测试、调优策略
一、性能測試
Ⅰ.測試方法
- 可以精準(zhǔn)定位到某個(gè)模塊或者某個(gè)方法的性能問題,例如對(duì)比一個(gè)方法使用同步實(shí)現(xiàn)和非同步實(shí)現(xiàn)的性能差異
- 宏基準(zhǔn)性能測試是一個(gè)綜合測試,需要考慮到測試環(huán)境、測試場景和測試目標(biāo)
- 測試環(huán)境:模擬線上的真實(shí)環(huán)境
- 測試場景:在測試某個(gè)接口時(shí),是否有其他業(yè)務(wù)的接口也在平行運(yùn)行,進(jìn)而造成干擾
- 測試目標(biāo)
- 可以通過吞吐量和響應(yīng)時(shí)間來衡量系統(tǒng)是否達(dá)標(biāo),如果不達(dá)標(biāo),就需要進(jìn)行優(yōu)化
- 如果達(dá)標(biāo),就繼續(xù)加大測試的并發(fā)數(shù),探底接口的TPS
- 除了關(guān)注接口的吞吐量和響應(yīng)時(shí)間外,還需要關(guān)注CPU、內(nèi)存和IO的使用率情況
Ⅱ.干擾因素
1.熱身問題
①. 在Java編程語言和環(huán)境中,.java文件編譯成.class文件后,需要通過解析器將字節(jié)碼轉(zhuǎn)換成本地機(jī)器碼才能運(yùn)行
②. 為了節(jié)約內(nèi)存和執(zhí)行效率,代碼在最初被執(zhí)行時(shí),解析器會(huì)率先解析執(zhí)行這段代碼
③. 隨著代碼被執(zhí)行的次數(shù)增加,當(dāng)JVM發(fā)現(xiàn)某個(gè)方法或代碼塊運(yùn)行得很頻繁時(shí),就會(huì)把這些代碼認(rèn)定為熱點(diǎn)代碼
- 為了提高熱點(diǎn)代碼的執(zhí)行效率,在運(yùn)行時(shí),JVM將通過即時(shí)編譯器(JIT)把這些代碼編譯成與本地平臺(tái)相關(guān)的機(jī)器碼
- 并進(jìn)行各層次的優(yōu)化,然后存儲(chǔ)在內(nèi)存中,之后每次運(yùn)行代碼時(shí),直接從內(nèi)存中獲取
④. 因此在剛開始運(yùn)行的階段,JVM會(huì)花費(fèi)很長的時(shí)間來全面優(yōu)化代碼,后面就能以最高性能運(yùn)行了
2. 測試結(jié)果不穩(wěn)定
①. 不穩(wěn)定因素:機(jī)器其他進(jìn)程的影響、網(wǎng)絡(luò)波動(dòng)、JVM GC的不確定性
①. 解決方案:通過多次測試,將測試結(jié)果求平均,只要能保證平均值在一個(gè)合理的范圍之內(nèi),并且波動(dòng)不大即可
3. 多JVM
①. 任意一個(gè)JVM都擁有整個(gè)系統(tǒng)的資源使用權(quán)
②. 如果一臺(tái)機(jī)器上只部署單獨(dú)的一個(gè)JVM,在做性能測試時(shí),測試結(jié)果會(huì)很好,但一臺(tái)機(jī)器上有多個(gè)JVM,則不一定
③. 盡量避免線程環(huán)境一臺(tái)機(jī)器部署多個(gè)JVM
二、性能分析
1.完成性能測試之后,需要輸出一份性能測試報(bào)告,測試結(jié)果需要包括
- 測試接口的吞吐量和響應(yīng)時(shí)間(平均、最大、最小)
- 服務(wù)器的CPU、內(nèi)存、磁盤IO、網(wǎng)絡(luò)IO使用率、JVM的GC情況
2.通過觀察性能指標(biāo),可以發(fā)現(xiàn)性能瓶頸,再通過自下而上的方式分析查找問題
- 首先從操作系統(tǒng)層面,查看系統(tǒng)的CPU、內(nèi)存、磁盤IO、網(wǎng)絡(luò)IO的使用率是否存在異常
- 再通過命令查找異常日志,通過分析日志,尋找導(dǎo)致性能瓶頸的原因
- 還可以從Java應(yīng)用的JVM層面下手,查看JVM的GC頻率以及內(nèi)存分配情況是否存在異常
- 如果系統(tǒng)和JVM層面都沒有出現(xiàn)異常情況,可以查看應(yīng)用服務(wù)業(yè)務(wù)層是否存在性能瓶頸
- 例如Java編程的問題、讀寫數(shù)據(jù)瓶頸
3.分析查找性能問題可以采用自下而上的方式,而解決性能問題,一般采用自上而下的方式逐級(jí)優(yōu)化
三、性能調(diào)優(yōu)
思路:業(yè)務(wù)調(diào)優(yōu) -> 編程調(diào)優(yōu) -> 系統(tǒng)調(diào)優(yōu)
Ⅰ. 優(yōu)化代碼
1.應(yīng)用層的問題代碼往往會(huì)因?yàn)楹谋M系統(tǒng)資源而暴露出來
2.例如某段代碼導(dǎo)致內(nèi)存溢出,這往往是將JVM的內(nèi)存耗盡了
- 這會(huì)引發(fā)JVM頻繁地發(fā)生GC,導(dǎo)致CPU居高不下,此時(shí)也會(huì)耗盡系統(tǒng)的CPU資源
3.還有一些非問題代碼導(dǎo)致的性能問題,比較難以發(fā)現(xiàn)
- 例如如果對(duì)LinkedList進(jìn)行for循環(huán)遍歷,每次循環(huán)獲取元素時(shí),都會(huì)遍歷一次list,讀效率很低
- 優(yōu)化方案:可以采用Iterator
Ⅱ. 優(yōu)化設(shè)計(jì)
1.面向?qū)ο笥泻芏嘣O(shè)計(jì)模式,可以用于優(yōu)化業(yè)務(wù)層以及中間件層的代碼設(shè)計(jì),進(jìn)而達(dá)到精簡代碼和提高整體性能的目的
2.例如單例模式在頻繁創(chuàng)建對(duì)象的場景中,可以共享一個(gè)對(duì)象,減少頻繁創(chuàng)建和銷毀對(duì)象帶來的性能開銷
Ⅲ. 優(yōu)化算法
1.合適的算法可以大大提升系統(tǒng)性能
2.例如在不同的場景中,使用合適的查找算法可以降低時(shí)間復(fù)雜度
Ⅳ. 時(shí)間換空間
1.如果系統(tǒng)對(duì)查詢的速度沒有很高的要求,但對(duì)存儲(chǔ)空間要求苛刻,可以考慮用時(shí)間換空間
2.例如String的intern方法,可以將重復(fù)率比較高的數(shù)據(jù)存儲(chǔ)在常量池,重復(fù)使用相同的對(duì)象,大大節(jié)省內(nèi)存空間
- 但由于常量池使用的是HashMap類型,如果存儲(chǔ)數(shù)據(jù)過多,就會(huì)導(dǎo)致查詢性能下降
Ⅴ. 空間換時(shí)間
1.使用存儲(chǔ)空間來提升訪問速度
2.例如MySQL的分庫分表
Ⅵ. 參數(shù)調(diào)優(yōu)
1.根據(jù)業(yè)務(wù)場景,合理地設(shè)置JVM的內(nèi)存空間和GC算法
2.另外,合理地設(shè)置Web容器的線程池大小和Linux操作系統(tǒng)的內(nèi)核參數(shù)
四、兜底策略
1.性能優(yōu)化策略,主要為了提高系統(tǒng)性能,而兜底策略,主要為了確保系統(tǒng)的穩(wěn)定性
2.限流
- 對(duì)系統(tǒng)的入口設(shè)置最大訪問限制,參考性能測試中探底的接口TPS
- 同時(shí)采用熔斷措施,友好地返回沒有成功的請(qǐng)求
3.智能橫向擴(kuò)容
- 當(dāng)訪問量超過某一個(gè)閾值時(shí),系統(tǒng)可以根據(jù)需求自動(dòng)橫向擴(kuò)容
4.提前擴(kuò)容
- 常用于高并發(fā)系統(tǒng),例如瞬時(shí)搶購
- 此時(shí)智能橫向擴(kuò)容無法滿足大量發(fā)生在瞬間的請(qǐng)求
5.Kubernetes可以實(shí)現(xiàn)智能橫向擴(kuò)容和提前擴(kuò)容Docker服務(wù)
五、總結(jié)
寫在最后的雞湯
加油努力吧!比你優(yōu)秀的對(duì)手在學(xué)習(xí),你的仇人在磨刀,你的閨蜜在減肥,隔壁老王在練腰, 我們必須不斷學(xué)習(xí),否則我們將被學(xué)習(xí)者超越!
趁年輕,使勁拼,給未來的自己一個(gè)交代!
更多資料
資料免費(fèi)獲取方式:轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)+關(guān)注后私信【架構(gòu)】即可獲取資料免費(fèi)領(lǐng)取方式!
領(lǐng)取資料的朋友就有一些忘記私信而錯(cuò)過寶貴資料,所以關(guān)鍵別忘了轉(zhuǎn)發(fā)后私信哦!
這些資料都以整理成了PDF文檔,如果有需要獲取到這個(gè)群里面的文檔的話幫忙轉(zhuǎn)發(fā)一下然后再關(guān)注我私信回復(fù)“架構(gòu)”得到獲取方式吧!即可進(jìn)群獲取下載!!!
更多Java架構(gòu)進(jìn)階資料展示
總結(jié)
以上是生活随笔為你收集整理的java获取cpu使用率_2019年阿里P8架构师的解析:最新Java性能测试、调优策略的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编写第一个Java程序:hellowor
- 下一篇: 依赖注入的三种方式_Java核心知识 S