深刻淺出 Java Concurrency (40): 併發總結 part 4 性能與伸縮性[轉]

性能與伸縮性

使用線程的一種說法是爲了提升性能。多線程可使程序充分利用閒置的資源,提升資源的利用率,同時可以並行處理任務,提升系統的響應性。 可是很顯然,引入線程的同時也引入了系統的複雜性。另外系統的性能並非老是隨着線程數的增長而老是提升。算法

 

性能與伸縮性

性能的提高一般意味着能夠用更少的資源作更多的事情。這裏資源是包括咱們常說的CPU週期、內存、網絡帶寬、磁盤IO、數據庫、WEB服務等等。 引入多線程能夠充分利用多核的優點,充分利用IO阻塞帶來的延遲,也能夠下降網絡開銷帶來的影響,從而提升單位時間內的響應效率。數據庫

爲了提升性能,須要有效的利用咱們現有的處理資源,同時也要開拓新的可用資源。例如,對於CPU而言,理想情況下但願CPU可以滿負荷工做。固然這裏滿負荷工做是指作有用的事情,而不是無謂的死循環或者等待。受限於CPU的計算能力,若是CPU達到了極限,那麼很顯然咱們充分利用了計算能力。對於IO而言(內存、磁盤、網絡等),若是達到了其對於的帶寬,這些資源的利用率也就上去了。理想情況下全部資源的能力都被用完了,那麼這個系統的性能達到了最大值。緩存

爲了衡量系統的性能,有一些指標用於定性、定量的分析。例如服務時間、等待時間、吞吐量、效率、可伸縮性、生成量等等。服務時間、等待時間等用於衡量系統的效率,即到底有多快。吞吐量、生成量等用於衡量系統的容量,即可以處理多少數據。除此以外,有效服務時間、中斷時間等用於能力系統的可靠性和穩定性等。網絡

可伸縮性的意思是指增長計算資源,吞吐量和生產量相應獲得的改進。 從算法的角度講,一般用複雜度來衡量其對應的性能。例如時間複雜度、空間複雜度等。多線程

 

Amdahl定律

並行的任務增長資源顯然可以提升性能,可是若是是串行的任務,增長資源並不必定可以獲得合理的性能提高。 Amdahl定律描述的在一個系統中,增長處理器資源對系統行的提高比率。 假定在一個系統中,F是必須串行化執行的比重,N是處理器資源,那麼隨着N的增長最多增長的加速比:架構

 

理論上,當N趨近於無窮大時,加速比最大值無限趨近於1/F。 這意味着若是一個程序的串行化比重爲50%,那麼並行化後最大加速比爲2倍。併發

加速比除了能夠用於加速的比率外,也能夠用於衡量CPU資源的利用率。若是每個CPU的資源利用率爲100%,那麼CPU的資源每次翻倍時,加速比也應該翻倍。 事實上,在擁有10個處理器的系統中,程序若是有10%是串行化的,那麼最多能夠加速1/(0.1+(1-0.1)/10)=5.3倍,換句話說CPU的利用率只用5.3/10=53%。而若是處理器增長到100倍,那麼加速比爲9.2倍,也就是說CPU的利用率只有個9.3%。性能

顯然增長CPU的數量並不能提升CPU的利用率。下圖描述的是隨着CPU的數量增長,不一樣串行化比重的系統的加速比。優化

 

很顯然,串行比重越大,增長CPU資源的效果越不明顯。操作系統

 

性能提高

性能的提高能夠從如下幾個方面入手。

 

系統平臺的資源利用率

一個程序對系統平臺的資源利用率是指某一個設備繁忙且服務於此程序的時間佔全部時間的比率。從物理學的角度講相似於有用功的比率。簡單的說就是:資源利用率=有效繁忙時間/總耗費時間。

也就說盡量的讓設備作有用的功,同時榨取其最大值。無用的循環可能會致使CPU 100%的使用率,但不必定是有效的工做。有效性一般難以衡量,一般只能以主觀來評估,或者經過被優化的程序的行爲來判斷是否提升了有效性。

 

延遲

延遲描述的是完成任務所耗費的時間。延遲有時候也成爲響應時間。若是有多個並行的操做,那麼延遲取決於耗費時間最大的任務。

 

多處理

多處理是指在單一系統上同時執行多個進程或者多個程序的能力。多處理能力的好處是能夠提升吞吐量。多處理能夠有效利用多核CPU的資源。

 

多線程

多線程描述的是同一個地址空間內同時執行多個線程的過程。這些線程都有不一樣的執行路徑和不一樣的棧結構。咱們說的併發性更多的是指針對線程。

 

併發性

同時執行多個程序或者任務稱之爲併發。單程序內的多任務處理或者多程序間的多任務處理都認爲是併發。

 

吞吐量

吞吐量衡量系統在單位之間內能夠完成的工做總量。對於硬件系統而言,吞吐量是物理介質的上限。在沒有達到物理介質以前,提升系統的吞吐量也能夠大幅度改進性能。同時吞吐量也是衡量性能的一個指標。

 

瓶頸

程序運行過程當中性能最差的地方。一般而言,串行的IO、磁盤IO、內存單元分配、網絡IO等均可能形成瓶頸。某些使用太頻繁的算法也有可能成爲瓶頸。

 

可擴展性

這裏的可擴展性主要是指程序或系統經過增長可以使用的資源而增長性能的能力。

 

線程開銷

假設引入的多線程都用於計算,那麼性能必定會有很大的提高麼? 其實引入多線程之後也會引入更多的開銷。

 

切換上下文

若是可運行的線程數大於CPU的內核數,那麼OS會根據必定的調度算法,強行切換正在運行的線程,從而使其它線程可以使用CPU週期。

切換線程會致使上下文切換。線程的調度會致使CPU須要在操做系統和進程間花費更多的時間片斷,這樣真正執行應用程序的時間就減小了。另外上下文切換也會致使緩存的頻繁進出,對於一個剛被切換的線程來講,可能因爲高速緩衝中沒有數據而變得更慢,從而致使更多的IO開銷。

 

內存同步

不一樣線程間要進行數據同步,synchronized以及volatile提供的可見性都會致使緩存失效。線程棧之間的數據要和主存進行同步,這些同步有一些小小的開銷。若是線程間同時要進行數據同步,那麼這些同步的線程可能都會受阻。

 

阻塞

當發生鎖競爭時,失敗的線程會致使阻塞。一般阻塞的線程可能在JVM內部進行自旋等待,或者被操做系統掛起。自旋等待可能會致使更多的CPU切片浪費,而操做系統掛起則會致使更多的上下文切換。

瞭解了性能的提高的幾個方面,也瞭解性能的開銷後,應用程序就要根據實際的場景進行取捨和評估。沒有一勞永逸的優化方案,不斷的進行小範圍改進和調整是提升性能的有效手段。當前一些大的架構調整也會致使較大的性能的提高。

簡單的原則是在保證邏輯正確的狀況小,找到性能瓶頸,小步改進和優化。

 

參考資料

相關文章
相關標籤/搜索