性能測試相關概念
并發(fā)用戶數(shù)(VU):?系統(tǒng)同時處理的request/事務數(shù)
QPS(TPS)(transaction per second):每秒鐘處理request/事務?數(shù)量
響應時間rt:??一般取平均響應時間
這三個參數(shù)是一組,理論上,并發(fā)數(shù)=QPS*rt,當QPS*rt<并發(fā)數(shù) 時,這時的壓力就接近系統(tǒng)所能承受的最大壓力了,也就是接近了系統(tǒng)瓶頸。
cpu使用率:cpu被占用的情況,一般要保證在75%以下
load:系統(tǒng)平均負載,被定義為在特定時間間隔(1m,5m,15m)內(nèi)運行隊列中的平均進程數(shù)。
前后優(yōu)化耗時:
1. 慎用try-catch,尤其是在循環(huán)之中,可以的話將其移到循環(huán)之外。循環(huán)內(nèi)110ms,循環(huán)外62ms
2. 多用局部變量。由于局部變量在棧中,其它如靜態(tài)變量的多在堆中,相比之下變量在棧中會更優(yōu)秀一些。使用static變量266ms,使用局部變量78ms。
3.位運算代替乘、除法。原219ms,位運算后31ms。
4.switch在循環(huán)中可以用數(shù)組代替(書中理論)。比較有意思的是我的本機上跑循環(huán)中switch耗時8ms,用map/array替代耗時32ms。
5.提取公共表達式。提取前156ms,提取后78ms。
6.展開循環(huán),拉開迭代器增長步長。有必要說一下,這會導致可讀性變差,也是沒有辦法的辦法才這么搞。優(yōu)化前94ms,優(yōu)化后31ms。
7.靜態(tài)static方法代替實例方法。
并發(fā)過程的優(yōu)化,這里也是有優(yōu)化策略的。首先由于數(shù)據(jù)同步,并發(fā)結構需要更改如下:
List : Collections.synchronizedList(List)
Set : Collections.synchronizedList(Set)
HashMap : concurrentHashMap
Queue : concurrentLinkedQueue
volatile : 變量其它線程可見
synchronized : 鎖方法,內(nèi)部鎖
ReadWriteLock : 重入鎖
ThreadLocal : 局部變量,每個變量一個副本
semaphore :信號量,指定多個線程同時訪問某一資源
關于鎖,有以下幾種方法:
1. 減小鎖的范圍,舉個例子,如果某條記錄操作數(shù)據(jù)庫,如果可以將這條記錄鎖住,那就千萬不要用鎖整個數(shù)據(jù)庫的方式,而使用將這條記錄鎖住。
2.減小鎖粒度。如concurrentHaspMap結構,其內(nèi)部是分為16段的,減少Hash時沖突問題。當然這也存在一個問題,就是concurrentHaspMap作為全局使用時,需要獲取全部的16個鎖。
3.鎖分離。LinkedBlockingQueue,基于鏈表前端、尾端同時操作;此外讀寫分離鎖(針對讀多寫少的情況)也是這個思想。
4.鎖粗化:循環(huán)內(nèi)頻繁使用鎖時,放在循環(huán)之外。
nGrinder
http://blog.csdn.net/neven7/article/details/50740018
Android 性能測試總結
啟動時間
啟動時間一般我們會測試三種情況。
首次啟動
非首次啟動
activity 切換所消耗的時間
測試方法一般使用兩種:
1、程序內(nèi)部打點到logcat,手動操作后獲取log日志,來獲取相應的時間。
2、使用adb 命令來操作,在操作的前后分別記錄消耗的時間。(由于adb 操作可能會有延時等可能,此方法并不是很準確)
ps. 還有一種方式是采用告訴攝像機的方式來做,由于本人沒有接觸過,不過多說明。
1、獲取cpu數(shù)據(jù)
adb shell dumpsys cpuinfo |grep$package_name
輸出格式為;
45% TOTAL:18%user+ 20% kernel +6.2% iowait +0.2% softirq
可取total得值作為整體cpu利用率。
2、獲取內(nèi)存數(shù)據(jù)
adb shell dumpsys meminfo |grep$package_name
或者
adbshell dumpsys meminfo$package_name
直接dumpsys meminfo $package_name 可以看到比較完整的堆,線程,java等級別的內(nèi)存數(shù)據(jù),pss 可以作為內(nèi)存的參考。
2、使用top 同時獲取cpu和內(nèi)存,-d 參數(shù)指定采樣數(shù)據(jù)的間隔時間。
adb shell top-d2
輸出:
PIDPR CPU% S#THR? ? VSS? ? RSS PCY UID? ? ? Name
名詞解釋:
VSS- Virtual Set Size 虛擬耗用內(nèi)存(包含共享庫占用的內(nèi)存)
RSS- Resident Set Size 實際使用物理內(nèi)存(包含共享庫占用的內(nèi)存)
PSS- Proportional Set Size 實際使用的物理內(nèi)存(比例分配共享庫占用的內(nèi)存)
USS- Unique Set Size 進程獨自占用的物理內(nèi)存(不包含共享庫占用的內(nèi)存)
一般來說內(nèi)存占用大小有如下規(guī)律:VSS >= RSS >= PSS >= USS
可以看到,top 命令取出的內(nèi)存對應是vss 和 rss,其中rss會比pss稍大,如果沒有特別嚴格的要求,只是對比內(nèi)存是否泄漏上漲等問題,rss也可以作為參考。
1、通過tcpdump抓包,然后wireshark 解包信息,來獲取流量數(shù)據(jù)。
2、通過adb 命令來獲取,先獲取應用的pid,然后通過/proc/uid_stat/uid/下的文件來讀取流量值。此方式會有rom兼容性問題,并不是所有的文件都可以找到這兩個文件。
adbshelldumpsys$package_nameadbshellcat/proc/uid_stat/uid/tcp_rcv? -- 下載流量adbshellcat/proc/uid_stat/uid/tcp_snd? -- 上傳流量
由于tcp_rcv, tcp_snd 的值是一個累加的值,想要獲取兩次操作間消耗的流量,可以在操作前和操作后分別獲取,差值即為期間消耗的流量。也可以每個一段時間做采樣,來獲取整個過程中的使用情況。
幀率一定程度上反應的是app在使用中的流暢程度,理想情況是每秒60幀。
1、在開發(fā)者選項中有個“ GPU呈現(xiàn)模式分析(Profile GPU rendering,計算adb shell dumpsys gfxinfo中的呈現(xiàn)時間)”功能,在開啟這個功能后,系統(tǒng)就會記錄保留每個界面最后128幀圖像繪制的相關時間信息。在開啟這個功能后,重新啟動APP,滑動頁面然后執(zhí)行adb命令。
adbshell dumpsys gfxinfo$package_name
輸出結果中包含這部分數(shù)據(jù)
DrawProcessExecute1.301.250.530.630.621.640.240.510.440.251.760.400.251.550.430.250.530.370.491.512.12
Draw: 表示在Java中創(chuàng)建顯示列表部分中,OnDraw()方法占用的時間。
Process:表示渲染引擎執(zhí)行顯示列表所花的時間,view越多,時間就越長。
Execute:表示把一幀數(shù)據(jù)發(fā)送到屏幕上排版顯示實際花費的時間。其實是實際顯示幀數(shù)據(jù)的后臺緩存區(qū)與前臺緩沖區(qū)交換后并將前臺緩沖區(qū)的內(nèi)容顯示到屏幕上的時間。
Draw + Process + Execute = 完整顯示一幀 ,這個時間要小于16ms才能保存每秒60幀。
2、通過SurfaceFlinger, 這種方式還沒有研究過,過段時間再來補充
adb shell dumpsys SurfaceFlinger
1、對于電量的測試沒有什么特別好的方式,可以選擇使用物理設備來測試電池的電量情況。
2、對于android 5.0 以上的系統(tǒng),adb命令可以支持獲取電量信息。
adbshelldumpsysbattery
輸出內(nèi)容如下:
ACpowered:falseUSBpowered:trueWirelesspowered:falsestatus:1#電池狀態(tài):2:充電狀態(tài) ,其他數(shù)字為非充電狀態(tài)health:2present:truelevel:55#電量: 百分比scale:100voltage:3977currentnow:-335232temperature:335#電池狀態(tài)technology:Li-poly
jvm的調(diào)優(yōu)
查看堆空間大小分配(年輕代、年老代、持久代分配)
垃圾回收監(jiān)控(長時間監(jiān)控回收情況)
?線程信息監(jiān)控:系統(tǒng)線程數(shù)量
線程狀態(tài)監(jiān)控:各個線程都處在什么樣的狀態(tài)下
線程詳細信息:查看線程內(nèi)部運行情況,死鎖檢查
CPU熱點:檢查系統(tǒng)哪些方法占用了大量CPU時間
內(nèi)存熱點:檢查哪些對象在系統(tǒng)中數(shù)量最大
服務器性能瓶頸如何定位

https://www.cnblogs.com/mumulog/p/11455018.html
CPU定位分析
CPU利用率大于50%,需要注意;大于75%,需要密切關注;高于90%-95%,情況比較嚴重;
監(jiān)控命令:vmstat、sar、dstat、mpstat、top、ps
類型度量方法衡量標準
利用率
1、vmstat統(tǒng)計1-%idle
2、sar -u統(tǒng)計1-%idle
3、dstat統(tǒng)計1-%idl
4、mpstat -P ALL統(tǒng)計1-%idle
注意>=50%
告警>=70%
嚴重>=90%
滿載
1、vmstat的r值>? cpu邏輯顆數(shù)
2、sar -q ,“runq-sz”>cpu邏輯顆數(shù)
運行隊列大于1時,證明已經(jīng)有一定的負載
內(nèi)存定位分析
當物理內(nèi)存不夠時,會使用swap分區(qū),所以性能測試過程中需要關注swap和mem的使用情況。
物理內(nèi)存不夠,大量的內(nèi)存置換到swap空間,可能導致CPU和I/O的瓶頸。
監(jiān)控命令:vmstat、sar、dstat、free、top、ps等
類型度量方法衡量標注
占用率
1、free 查看使用情況
2、vmstat
3、sar -r
4、ps
注意>=50%
告警>=70%
嚴重>=80%
滿載
1、vmstat的si/so比例,swapd占比
2、sar -W 查看次缺頁數(shù)
3、dmesg | grep killed
1、so數(shù)值大,且swapd已經(jīng)占比很高,內(nèi)存已經(jīng)飽和
2、sar命令次缺頁多意味內(nèi)存已經(jīng)飽和
3、內(nèi)存不夠用會觸發(fā)內(nèi)核的OOM機制
網(wǎng)絡定位分析
監(jiān)控命令:sar、ifconfig、netstat,以及查看net的dev速率。
通過查看發(fā)現(xiàn)收發(fā)包的吞吐率達到網(wǎng)卡的最大上限,網(wǎng)絡數(shù)據(jù)報文有因為這類原因而引起的丟包、阻塞等現(xiàn)象都證明當前網(wǎng)絡可能存在瓶頸。
為了減小網(wǎng)絡對性能測試的影響,一般我們都在局域網(wǎng)中進行測試執(zhí)行。
類型度量方法衡量標準
使用情況
1、sar -n DEV 的收發(fā)計數(shù)大于網(wǎng)卡上限
2、ifconfig RX/TX寬帶超過網(wǎng)卡上限
3、cat /proc/net/dev的速率超過上限
4、nicstat的util基本滿負荷
1、收發(fā)包的吞吐率達到網(wǎng)卡上限
2、有延遲
3、有丟包
4、有阻塞
滿載1、ifconfig dropped 有計數(shù)
2、netstat -s "segments retransmited"有計數(shù)
3、sar -n EDEV,rxdrop/s ?txdrop/s有計數(shù)
有丟包統(tǒng)計
錯誤
1、ifconfig,“errors”
2、netstat -i,RX-ERR TX-ERR
3、sar -n EDEV,rxerr/s ? txerr/s?
4、ip -s link, “errors”
錯誤有計數(shù)? ?
IO定位分析
I/O讀寫頻繁的時候,如果I/O得不到滿足會導致應用的阻塞。
需要考慮I/O的TPS、平均I/O數(shù)據(jù)、平均隊列長度、平均服務時間、平均等待時間、IO利用率(磁盤Busy Time%)等指標
監(jiān)控命令:sar、iostat、iotop
類型度量方法衡量標準
使用情況
1、iostat -xz,“%util”
2、sar -d,“%util”
3、cat /proc/pid/sched | grep iowait
注意>=40%
告警>=60%
嚴重>=80%
滿載
1、iostat -xnz,“avgqu-sz?”>1
2、iostat await>70
IO疑似滿載
錯誤
1、dmseg 查看io錯誤
2、smartctl /dev/sda
有錯誤信息
Jmeter知識
一臺臺式機能支持的最大并發(fā)量 This is based on my experience If we follow the best practices as follow then we can achieve?350?~?500?concurrent users (web based application) and?900~1100?concurrent users (backend API) provided 8 GB RAM with 64-bit OS.
1、如何配置多個用戶--放在csv文件里面,進行調(diào)用
2、前面一個接口的返回值,比如登錄的token值,如何作為下一個接口的參數(shù),進行傳輸--后置處理器中的正則表達式去提取,或者json提取器
3、加密參數(shù)如何傳輸--調(diào)用一個函數(shù)--https://www.cnblogs.com/kikihuang/p/11475669.html
4、如何處理異步通信
https://blog.csdn.net/weixin_42484338/article/details/102851774?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.baidujs&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.baidujs
5、壓力測試在測試環(huán)境還是線上環(huán)境做?如果是測試環(huán)境做,如何保證和線上環(huán)境一樣?因為測試環(huán)境配置的服務器啥的大多和線上不一樣
6、分布式壓測了解一下
https://www.cnblogs.com/gcgc/p/11727761.html
https://www.cnblogs.com/dcszhangsir/p/13463299.html
7、根據(jù)測試報告的數(shù)據(jù),如何分析測試結果,并給出開發(fā)一些修改意見
8、壓力測試主要分析哪些測試指標
9、遇到過得測試出來的什么問題,是什么原因,給出了什么建議,大概講一下
gatling
全鏈路壓測
1)首先要梳理核心鏈路的流程,明確鏈路的邊界,核心鏈路是一個業(yè)務的核心,這一塊應該可以很快梳理清楚,但是,難點在于梳理清楚鏈路的邊界,分支業(yè)務
每個業(yè)務owner反復確認,哪些是核心業(yè)務,哪些是分支業(yè)務,哪些參與壓測,哪些不參與壓測,把這些形成文檔,逐個跟進。
2)提供全鏈路壓測的底層支持
我的理解:
流量、數(shù)據(jù)隔離 ,可以在head中打標
新建影子表,寫入和讀取都走影子表
日志-影子目錄:將壓測流量產(chǎn)生的日志落入到影子目錄
全鏈路透傳壓測標志:必須有一種在全鏈路透傳壓測標志的能力,并且必須基于一次請求,也就是同一個traceId,現(xiàn)在,大部分分布式業(yè)務都會接入trace系統(tǒng),例如,google的dapper,阿里的鷹眼等,對trace系統(tǒng)進行改造,使其能夠透傳壓測標志,需要透傳的路徑大概有:
? ? HTTP,RPC(DUBBO),MQ,線程池等
影子表:參與壓測的業(yè)務,要逐個排查自己依賴的數(shù)據(jù)庫,然后創(chuàng)建影子表,影子表必須跟正常表的schema保持一致,可以在每次壓測時候手動創(chuàng)建,也可以推動DBA自動創(chuàng)建。創(chuàng)建好影子表后,如果當前流量是壓測流量,那么寫入和讀取都走影子表。如果有自己的數(shù)據(jù)庫中間件最好,沒有的話可以借助于Mybatis的Interceptor機制。
日志-影子目錄:為了防止壓測流程的日志對正常日志造成干擾,需要改造日志組件,將壓測流量產(chǎn)生的日志落入到影子目錄。影子目錄可以有日志組件自動創(chuàng)建。
MQ支持是否消費壓測流量:有的時候,全鏈路會通過MQ進行傳遞,所以,必須在消費MQ的時候進行選擇:是否選擇消費壓測流量的MQ消息。這就需要對MQ系統(tǒng)進行改造,一方面使其可以透傳壓測流量,另一方面,需要支持配置是否消費壓測的MQ消息
緩存,大數(shù)據(jù)隔離:還有一些場景,比如,緩存層,大數(shù)據(jù)層對壓測流量的處理也要考慮隔離。緩存可以使用不同的集群;大數(shù)據(jù)可以直接不收集壓測的數(shù)據(jù)
3)思考全鏈路壓測的數(shù)據(jù)怎么mock
在使用影子表之后,可以比較輕松的實現(xiàn)跟正常數(shù)據(jù)隔離,那剩下的就是好構造好mock數(shù)據(jù),有幾點需要考慮:
① 用戶數(shù)據(jù)要提前做好認證等準備工作
②? Mock數(shù)據(jù)要盡可能跟真實數(shù)據(jù)保持一致,比如,價格水平,圖片數(shù)量,地址信息等等
③? Mock數(shù)據(jù)有些限制需要放開,比如,庫存,一些運營性質(zhì)的活動可以取消等
④ 千萬不要污染正常數(shù)據(jù):認真梳理數(shù)據(jù)處理的每一個環(huán)節(jié),確保mock數(shù)據(jù)的處理結果不會寫入到正常庫里面
4)梳理監(jiān)控體系
① 核心接口和核心依賴的流量和耗時監(jiān)控
② 中間件組件,緩存,數(shù)據(jù)庫的監(jiān)控報警
③ 機器的指標報警
5)線下做好預演
真實的壓測之前,肯定要進行預演,預演主要確認:
① 壓測流程是否寫入到了正確的目的地,例如,寫入到影子表,影子目錄,壓測cache等等
② 壓測流量的降級是否完備和有效
③ 進一步確保監(jiān)控都已到位
6)盡量模擬現(xiàn)實,用戶的行為,例如
① 購買的行為:不是下單后立即購買,而是要等一下子
② 騎車子的行為:開鎖后并不是里面換車,而是騎一會
7)逐步平滑加壓
壓測的時候,逐步加壓,并且要保持平滑加壓,不要把一秒的流量都在前面幾毫秒內(nèi)都壓出去。
難點: 推進
全鏈路壓測的技術難點不多,除了要花時間梳理流程和思考如何處理數(shù)據(jù)之外,最難的就是整個鏈路跨多個業(yè)務,甚至部門,需要跟進每個業(yè)務線的進度,確保大家能夠在給定的時間點進行聯(lián)調(diào)以及進行壓測。在推進的時候,按照核心鏈路所在的模塊進行跟進,每個模塊出一個owner,各個owner跟進核心的接口和依賴,每周大家碰一下同步下總體的進度
壓測中TPS上不去,那么你怎么分析這個問題?
1、網(wǎng)絡帶寬
在壓力測試中,有時候要模擬大量的用戶請求,如果單位時間內(nèi)傳遞的數(shù)據(jù)包過大,超過了帶寬的傳輸能力,那么就會造成網(wǎng)絡資源競爭,間接導致服務端接收到的請求數(shù)達不到服務端的處理能力上限。
2、連接池
可用的連接數(shù)太少,造成請求等待。連接池一般分為服務器連接池(比如Tomcat)和數(shù)據(jù)庫連接池(或者理解為最大允許連接數(shù)也行)。
3、垃圾回收機制
從常見的應用服務器來說,比如Tomcat,因為java的的堆棧內(nèi)存是動態(tài)分配,具體的回收機制是基于算法,如果新生代的Eden和Survivor區(qū)頻繁的進行Minor GC,老年代的full GC也回收較頻繁,那么對TPS也是有一定影響的,因為垃圾回收其本身就會占用一定的資源。
4、數(shù)據(jù)庫配置
高并發(fā)情況下,如果請求數(shù)據(jù)需要寫入數(shù)據(jù)庫,且需要寫入多個表的時候,如果數(shù)據(jù)庫的最大連接數(shù)不夠,或者寫入數(shù)據(jù)的SQL沒有索引沒有綁定變量,抑或沒有主從分離、讀寫分離等,就會導致數(shù)據(jù)庫事務處理過慢,影響到TPS。
5、通信連接機制
串行、并行、長連接、管道連接等,不同的連接情況,也間接的會對TPS造成影響。
6、硬件資源
包括CPU(配置、使用率等)、內(nèi)存(占用率等)、磁盤(I/O、頁交換等)。
7、壓力機
比如jmeter,單機負載能力有限,如果需要模擬的用戶請求數(shù)超過其負載極限,也會間接影響TPS(這個時候就需要進行分布式壓測來解決其單機負載的問題)。
8、壓測腳本
還是以jemter舉個例子,之前工作中同事遇到的,進行階梯式加壓測試,最大的模擬請求數(shù)超過了設置的線程數(shù),導致線程不足。提到這個原因,想表達意思是:有時候測試腳本參數(shù)配置等原因,也會影響測試結果。
9、業(yè)務邏輯
業(yè)務解耦度較低,較為復雜,整個事務處理線被拉長導致的問題。
10、系統(tǒng)架構
比如是否有緩存服務,緩存服務器配置,緩存命中率、緩存穿透以及緩存過期等,都會影響到測試結果。
性能測試CPU占有率高如何定位問題?
通過Top命令查看具體的進程,然后使用相關的命令具體到線程,最后通過相關的工具查看棧的問題,以至于最后定位到代碼。
?總結:?
1. 查找進程
top查看進程占用資源情況
明顯看出java的那個進程占用過高cpu.
2.查找線程
使用top -H -p <pid>查看線程占用情況
3.查找java的堆棧信息
將線程id轉(zhuǎn)換成十六進制
#printf %x 15664
#3d30
然后再使用jstack查詢線程的堆棧信息
語法:jstack | grep -a?線程id(十六進制)
jstack <pid> | grep -a?3d30?
這樣就找出了有問題的代碼了。
?pid :進程id? ? ? ? ? ? ? ? tid :線程 id
https://blog.csdn.net/lord_is_layuping/article/details/90238816
Explain命令在解決數(shù)據(jù)庫性能上是第一推薦使用命令,大部分的性能問題可以通過此命令來簡單的解決,Explain可以用來查看?SQL?語句的執(zhí)行效 果,可以幫助選擇更好的索引和優(yōu)化查詢語句,寫出更好的優(yōu)化語句。
Explain語法:explain select … from … [where ...]
https://blog.csdn.net/jwq101666/article/details/78561022