個人專題目錄
深入了解性能優(yōu)化
1.常用的性能評價/測試指標
-
響應(yīng)時間
- 提交請求和返回該請求的響應(yīng)之間使用的時間,一般比較關(guān)注平均響應(yīng)時間。
-
并發(fā)數(shù)
- 同一時刻,對服務(wù)器有實際交互的請求數(shù)。
和網(wǎng)站在線用戶數(shù)的關(guān)聯(lián):1000個同時在線用戶數(shù),可以估計并發(fā)數(shù)在5%到15%之間,也就是同時并發(fā)數(shù)在50~150之間。
- 同一時刻,對服務(wù)器有實際交互的請求數(shù)。
-
吞吐量
- 對單位時間內(nèi)完成的工作量(請求)的量度
-
相互之間的關(guān)系
- 系統(tǒng)吞吐量和系統(tǒng)并發(fā)數(shù)以及響應(yīng)時間的關(guān)系:
理解為高速公路的通行狀況:
吞吐量是每天通過收費站的車輛數(shù)目(可以換算成收費站收取的高速費),
并發(fā)數(shù)是高速公路上的正在行駛的車輛數(shù)目,
響應(yīng)時間是車速。
車輛很少時,車速很快。但是收到的高速費也相應(yīng)較少;隨著高速公路上車輛數(shù)目的增多,車速略受影響,但是收到的高速費增加很快;
隨著車輛的繼續(xù)增加,車速變得越來越慢,高速公路越來越堵,收費不增反降;
如果車流量繼續(xù)增加,超過某個極限后,任務(wù)偶然因素都會導致高速全部癱瘓,車走不動,當然后也收不著,而高速公路成了停車場(資源耗盡)。
2.常用的性能優(yōu)化手段
-
總原則
-
避免過早優(yōu)化
不應(yīng)該把大量的時間耗費在小的性能改進上,過早考慮優(yōu)化是所有噩夢的根源。
所以,我們應(yīng)該編寫清晰,直接,易讀和易理解的代碼,真正的優(yōu)化應(yīng)該留到以后,等到性能分析表明優(yōu)化措施有巨大的收益時再進行。
但是過早優(yōu)化,不表示我們應(yīng)該編寫已經(jīng)知道的對性能不好的的代碼結(jié)構(gòu)。 -
進行系統(tǒng)性能測試
所有的性能調(diào)優(yōu),都有應(yīng)該建立在性能測試的基礎(chǔ)上,直覺很重要,但是要用數(shù)據(jù)說話,可以推測,但是要通過測試求證。
-
尋找系統(tǒng)瓶頸,分而治之,逐步優(yōu)化
性能測試后,對整個請求經(jīng)歷的各個環(huán)節(jié)進行分析,排查出現(xiàn)性能瓶頸的地方,定位問題,分析影響性能的的主要因素是什么?內(nèi)存、磁盤IO、網(wǎng)絡(luò)、CPU,還是代碼問題?架構(gòu)設(shè)計不足?或者確實是系統(tǒng)資源不足?
-
-
前端優(yōu)化手段
-
瀏覽器/App
- 減少請求數(shù);
合并CSS,Js,圖片
- 使用客戶端緩沖;
靜態(tài)資源文件緩存在瀏覽器中,有關(guān)的屬性Cache-Control和Expires
如果文件發(fā)生了變化,需要更新,則通過改變文件名來解決。- 啟用壓縮
減少網(wǎng)絡(luò)傳輸量,但會給瀏覽器和服務(wù)器帶來性能的壓力,需要權(quán)衡使用。
- 資源文件加載順序
css放在頁面最上面,js放在最下面
- 減少Cookie傳輸
cookie包含在每次的請求和響應(yīng)中,因此哪些數(shù)據(jù)寫入cookie需要慎重考慮
- 給用戶一個提示
有時候在前端給用戶一個提示,就能收到良好的效果。畢竟用戶需要的是不要不理他。
- CDN加速
CDN,又稱內(nèi)容分發(fā)網(wǎng)絡(luò),本質(zhì)仍然是一個緩存,而且是將數(shù)據(jù)緩存在用戶最近的地方。無法自行實現(xiàn)CDN的時候,可以考慮商用CDN服務(wù)。
- 反向代理緩存
將靜態(tài)資源文件緩存在反向代理服務(wù)器上,一般是Nginx。
- WEB組件分離
將js,css和圖片文件放在不同的域名下??梢蕴岣邽g覽器在下載web組件的并發(fā)數(shù)。因為瀏覽器在下載同一個域名的的數(shù)據(jù)存在并發(fā)數(shù)限制。
-
應(yīng)用服務(wù)性能優(yōu)化
-
存儲性能優(yōu)化
- 選擇合適的數(shù)據(jù)結(jié)構(gòu)
選擇ArrayList和LinkedList對我們的程序性能影響很大,為什么?因為ArrayList內(nèi)部是數(shù)組實現(xiàn),存在著不停的擴容和數(shù)據(jù)復制。
- 選擇更優(yōu)的算法
舉個例子,最大子列和問題:
給定一個整數(shù)序列,a0, a1, a2, …… , an(項可以為負數(shù)),求其中最大的子序列和。
如果所有整數(shù)都是負數(shù),那么最大子序列和為0;
例如(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)時,
最大子段和為20,子段為a[2],a[3],a[4]。
最壞的算法:窮舉法,所需要的的計算時間是O(n^3).
一般的算法:分治法的計算時間復雜度為O(nlogn).
最好的算法:最大子段和的動態(tài)規(guī)劃算法,計算時間復雜度為O(n)
n越大,時間就相差越大,比如10000個元素,最壞的算法和最好的算法之間的差距絕非多線程或者集群化能輕松解決的。- 編寫更少的代碼
同樣正確的程序,小程序比大程序要快,這點無關(guān)乎編程語言。
3.應(yīng)用服務(wù)性能優(yōu)化
-
緩存
- 緩存的基本原理和本質(zhì)
- 緩存是將數(shù)據(jù)存在訪問速度較高的介質(zhì)中??梢詼p少數(shù)據(jù)訪問的時間,同時避免重復計算。
- 合理使用緩沖的準則
- 頻繁修改的數(shù)據(jù),盡量不要緩存,讀寫比2:1以上才有緩存的價值。
- 緩存一定是熱點數(shù)據(jù)。
應(yīng)用需要容忍一定時間的數(shù)據(jù)不一致。 - 緩存可用性問題,一般通過熱備或者集群來解決。
- 緩存預(yù)熱,新啟動的緩存系統(tǒng)沒有任何數(shù)據(jù),可以考慮將一些熱點數(shù)據(jù)提前加載到緩存系統(tǒng)。
- 解決緩存擊穿:
1、布隆過濾器,或者2、把不存在的數(shù)據(jù)也緩存起來 ,比如有請求總是訪問key = 23的數(shù)據(jù),但是這個key = 23的數(shù)據(jù)在系統(tǒng)中不存在,可以考慮在緩存中構(gòu)建一個( key=23 value = null)的數(shù)據(jù)。
- 分布式緩存與一致性哈希
- 以集群的方式提供緩存服務(wù),有兩種實現(xiàn);
- 需要更新同步的分布式緩存,所有的服務(wù)器保存相同的緩存數(shù)據(jù),帶來的問題就是,緩存的數(shù)據(jù)量受限制,其次,數(shù)據(jù)要在所有的機器上同步,代價很大。
- 每臺機器只緩存一部分數(shù)據(jù),然后通過一定的算法選擇緩存服務(wù)器。常見的余數(shù)hash算法存在當有服務(wù)器上下線的時候,大量緩存數(shù)據(jù)重建的問題。所以提出了一致性哈希算法。
- 一致性哈希
- 首先求出服務(wù)器(節(jié)點)的哈希值,并將其配置到0~232的圓(continuum)上
- 然后采用同樣的方法求出存儲數(shù)據(jù)的鍵的哈希值,并映射到相同的圓上。
- 然后從數(shù)據(jù)映射到的位置開始順時針查找,將數(shù)據(jù)保存到找到的第一個服務(wù)器上。如果超過232仍然找不到服務(wù)器,就會保存到第一臺服務(wù)器上。
- 一致性哈希算法對于節(jié)點的增減都只需重定位環(huán)空間中的一小部分數(shù)據(jù),具有較好的容錯性和可擴展性。
- 一致性哈希算法在服務(wù)節(jié)點太少時,容易因為節(jié)點分部不均勻而造成數(shù)據(jù)傾斜問題,此時必然造成大量數(shù)據(jù)集中到Node A上,而只有極少量會定位到Node B上。為了解決這種數(shù)據(jù)傾斜問題,一致性哈希算法引入了虛擬節(jié)點機制,即對每一個服務(wù)節(jié)點計算多個哈希,每個計算結(jié)果位置都放置一個此服務(wù)節(jié)點,稱為虛擬節(jié)點。具體做法可以在服務(wù)器ip或主機名的后面增加編號來實現(xiàn)。例如,可以為每臺服務(wù)器計算三個虛擬節(jié)點,于是可以分別計算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六個虛擬節(jié)點:同時數(shù)據(jù)定位算法不變,只是多了一步虛擬節(jié)點到實際節(jié)點的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三個虛擬節(jié)點的數(shù)據(jù)均定位到Node A上。這樣就解決了服務(wù)節(jié)點少時數(shù)據(jù)傾斜的問題。在實際應(yīng)用中,通常將虛擬節(jié)點數(shù)設(shè)置為32甚至更大,因此即使很少的服務(wù)節(jié)點也能做到相對均勻的數(shù)據(jù)分布。
- 以集群的方式提供緩存服務(wù),有兩種實現(xiàn);
- 緩存的基本原理和本質(zhì)
集群
-
異步
- 同步和異步,阻塞和非阻塞
- 常見異步的手段
- Servlet異步
- servlet3中才有,支持的web容器在tomcat7和jetty8以后。
- 多線程
- 消息隊列
- 集群
- 可以很好的將用戶的請求分配到多個機器處理,對總體性能有很大的提升
- 程序代碼級別
- Servlet異步
-
應(yīng)用相關(guān)
- 代碼級別
- 選擇合適的數(shù)據(jù)結(jié)構(gòu)
- 選擇更優(yōu)的算法
- 編寫更少的代碼
- 并發(fā)編程
- 充分利用CPU多核
- 實現(xiàn)線程安全的類,避免線程安全問題
- 同步下減少鎖的競爭
- 資源的復用
- 目的是減少開銷很大的系統(tǒng)資源的創(chuàng)建和銷毀,比如數(shù)據(jù)庫連接,網(wǎng)絡(luò)通信連接,線程資源等等。
- JVM
- 對于程序來說,通常只有一部分代碼被經(jīng)常執(zhí)行,這些關(guān)鍵代碼被稱為應(yīng)用的熱點,執(zhí)行的越多就認為是越熱。將這些代碼編譯為本地機器特定的二進制碼,可以有效提高應(yīng)用性能。
- 存儲性能優(yōu)化
- 盡量使用SSD
- 定時清理數(shù)據(jù)或者按數(shù)據(jù)的性質(zhì)分開存放
- 代碼級別