真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

性能優(yōu)化=改改代碼?

如果第二次看到我的文章,歡迎「文末」掃碼關注我喲~ 

為麗水等地區(qū)用戶提供了全套網(wǎng)頁設計制作服務,及麗水網(wǎng)站建設行業(yè)解決方案。主營業(yè)務為網(wǎng)站建設、網(wǎng)站設計、麗水網(wǎng)站設計,以傳統(tǒng)方式定制建設網(wǎng)站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!

每周五11:45 按時送達。  當然了,也會時不時加個餐~

我的第「124」篇原創(chuàng)敬上

大家好,我是Z哥。


好久沒寫技術文章了,最近正好有進行一些思考,順手寫出來分享給大家。

上了一定規(guī)模的系統(tǒng),特別是To C的系統(tǒng),性能優(yōu)化或多或少都會被逼著去做一下。否則,系統(tǒng)便無法支撐業(yè)務的發(fā)展,技術成了拖后腿,不是引領業(yè)務了。

一旦線上出現(xiàn)了性能問題,就會很棘手。因為它和業(yè)務功能上的Bug不同,后者的分析和解決思路更清晰,只要日志記錄到位,沿著一條已知的業(yè)務邏輯線,很容易就能找到問題根源。

而性能問題就會復雜的多,導致的因素有很多,甚至會是多種因素共同作用下的結果。比如,代碼質量低下、業(yè)務發(fā)展太快、架構設計不合理等等。

而且一般情況下,性能問題處理起來比較耗時,涉及到的分析鏈路可能會很長,特別是自己小組之外的上下游系統(tǒng),很多人不愿意干,或者說有心無力。最多采用一些臨時性的補救手段,碰碰運氣。比如,擴容增加機器、重啟大招、……。

有些臨時性的補救措施,有時候不但不能解決問題,還會埋下新的隱患。

比如,從表象上看到某個程序因為給的資源不足導致產生性能問題。臨時增加更多資源給它,可能從表面上看,問題是解決了。但是實則可能是因為程序內部對資源的使用上存在不合理的地方,增加資源只是延緩問題發(fā)作的時間,而且還可能會侵占其它程序的運行資源。

為了避免陷入如此的窘境,我們應當盡量提前進行性能優(yōu)化,未雨綢繆。甚至最好是將它作為一個周期性的工作來進行。
接下去就來分享一下我對做性能優(yōu)化的思路。

/01 明確優(yōu)化目的/


很多人優(yōu)化優(yōu)化著慢慢變成了為了優(yōu)化而優(yōu)化,目的丟了,或者甚至一開始就沒考慮過。如此會陷入到無意義的性能黑洞中,無法自拔,只是不斷追求更好看的性能指標。

優(yōu)化的目的可以是增強用戶體驗,比如消除一些有明顯卡頓的頁面和操作。還可以是節(jié)省服務器帶寬流量、減少服務器壓力這些。無論如何,你需要有一個目的。

/02 定標準,做到什么程度/


優(yōu)化這事是永無止境的,為了避免陷入到前面說的無意義的性能黑洞中,我們最好能夠根據(jù)實際的業(yè)務情況定義出一個相對客觀的標準,代表優(yōu)化到什么程度。
我自己慣用的標準是確保比預期高50%,如果條件允許則爭取到100%。

比如,根據(jù)當下的性能指標與業(yè)務量對比,發(fā)現(xiàn)最大并發(fā)數(shù)可能會超過當前的2倍,那么此時優(yōu)化到爭取優(yōu)化提升3倍,至少保證能提升2.5倍,是一個比較合理的標準。
之前專門寫過一篇關于容量預估的文章《 做「容量預估」可沒有true和false》,可以在文末跳轉過去看下,這里就不展開了。

/03 找到瓶頸點/


很多人做優(yōu)化的時候,逮著代碼就開始改。的確,只要有一定的知識積累,很容易就能從代碼中發(fā)現(xiàn),寫法A不如寫法B這樣的代碼。

但其實大部分情況下,「 流程上的優(yōu)化遠勝于語法級別的優(yōu)化」。比如將每一個字符串拼接改成用StringBuilder來實現(xiàn),大多數(shù)情況下帶來的成果其實很小,甚至在某些情況下還不如不改。
所以,我們最好還是能夠借助一些客觀數(shù)據(jù),以獲得更多的運行環(huán)境相關的信息,來找到整個“木桶”上最短的一塊“板”。如整個系統(tǒng)的總體架構、服務器的信息等,便于定位到底性能的瓶頸點在哪。

「流程上的優(yōu)化遠勝于語法級別的優(yōu)化」中的“流程”除了業(yè)務流程之外,還包括技術層面的流程,比如數(shù)據(jù)在網(wǎng)絡中的流轉過程。

/04 著手優(yōu)化/


最后才是著手優(yōu)化。

做優(yōu)化的時候需要避免兩個常見的誤區(qū)。

第一, 不要過度追求應用的單機性能,如果單機表現(xiàn)良好,還應該從整體的角度去思考。

第二, 要過度追求單一維度上的極致優(yōu)化,比如過度追求 CPU 的性能而忽略了內存方面的瓶頸。

正確的思路一般符合下面兩個方向。

第一, 空間換性能。一個節(jié)點頂不住就多復制一個節(jié)點出來,獨一份的數(shù)據(jù)導致資源競爭得厲害,就多復制一份數(shù)據(jù)出來。

第二, 距離換性能。數(shù)據(jù)從服務端經過層層處理返回到客戶端覺得慢的話,那么能不能直接保存在客戶端,或者至少是離客戶端盡可能近的地方。

好了,思路清楚了,具體在做的時候我建議你根據(jù)下面小標題的順序進行。不管是主動地性能優(yōu)化,還是被動地排查性能問題都一樣。

/01 應用程序層面/

不管你愿不愿意承認,現(xiàn)實中的大部分性能問題皆是應用程序自身部分的代碼導致的。
我們總是不太愿意承認自己的錯誤,我見過太多程序員總是習慣性的將問題先歸結于硬件問題,網(wǎng)絡問題等等,然后最終排查下來的根源往往還是在coding的應用程序上。

所以,我們更應該先從應用程序本身入手進行分析。而且, 應用程序所處的位置更「上游」,可操作性更強,讓我們可以有更多的手段進行優(yōu)化。


01   緩存

首先,最常見的便是「緩存」,這是用空間換性能的經典。

數(shù)據(jù)必然是存儲在非易失性的數(shù)據(jù)庫中的,但是一些會被高頻訪問的數(shù)據(jù),將它從數(shù)據(jù)庫中復制一份,存儲在易失性的內存上做緩存,可以大大提高被訪問的性能。這個道理大家都懂,就不多說了。

但是值得提醒的一點是,緩存數(shù)據(jù)的數(shù)據(jù)結構設計很重要,沒有一種數(shù)據(jù)結構是萬能的。需要更多的權衡,因為數(shù)據(jù)結構設計的越簡單、單一,緩存數(shù)據(jù)的二次運算就越多;反之,所有都存儲「結果數(shù)據(jù)」的話,需要冗余的數(shù)據(jù)量又過大(緩存數(shù)據(jù)更新還麻煩)。

還得提醒一點,如果緩存的數(shù)據(jù)量不小,還得考慮增加一個緩存淘汰算法,否則緩存命中率不堪入目,白白浪費大量內存資源。

之前的《 分布式系統(tǒng)系列》中有幾篇緩存相關的聊了很多細節(jié),可以在文末跳過去查閱。

02   異步

舉個現(xiàn)實生活中的例子,如果你在手機上點了一杯奶茶,去店里拿的時候發(fā)現(xiàn)前面還有20個號,你會在這干等半小時么?

我想大部分人都不會吧,寧愿去別的地方溜溜。異步就是通過避免“干等著”來提升性能的手段。

做異步主要是以下兩種方式,

  • 通過線程進行異步。這主要用于涉及到I/O的地方,像磁盤I/O和網(wǎng)絡I/O。一旦產生I/O其實就意味著背后的操作是由另外一個程序在進行,此時CPU就不用空著了,讓它忙別的去吧。

     

  • 通過中間件異步,比如MQ。這用于更大的場景里,比如在某些流程中、上下游系統(tǒng)的銜接中,如果有些結果并不需要實時收到,那么通過MQ進行異步就可以大大提高性能。畢竟MQ的性能更接近NOSQL,性能自然比關系型數(shù)據(jù)庫高的多。更何況,還將一些業(yè)務邏輯的預算給滯后了,當下的性能會更好。

 

 


03  多線程&分布式

這兩點都是「分治」思想的體現(xiàn)。一個快遞員送1000個包裹比較慢,那么讓10個快遞員同時各送100個自然就快了。

但是切勿分的太狠,畢竟,多起一個線程相當于多一個放養(yǎng)的娃,放出去太多的話,管理成本很高,可能反而會更慢。這就是線程切換的成本,分布式系統(tǒng)中也存在類似的管理成本。

不過,一個小建議送給你。 不到迫不得已,能通過「單機多線程」應付的,就不要引入分布式了。因為,網(wǎng)絡這個東西實在太不靠譜了,你得為它做大量的額外工作。

04  延后運算

這個和緩存的思路相反,將一些運算盡可能的延后到用的時候。適用的場景也和緩存相反,適用于一些低頻的、運算耗時的數(shù)據(jù)上。

延遲加載、插件化等等就是該思想的體現(xiàn)。

05  批量,合并

如果你需要在短時間內頻繁的傳遞多個數(shù)據(jù)給同一個目的地,那么盡量考慮將他們打包到一起,一次性傳輸,特別是涉及到I/O的場景。

如果手頭的系統(tǒng)還是一個單點系統(tǒng),這招的性價比就非常高。在避開分布式系統(tǒng)的復雜性的前提下,獲得性能提升。

數(shù)據(jù)庫的bulk操作,前端的sprite圖,都是該思想的體現(xiàn)。

應用程序層面的其它優(yōu)化方式還有很多。比如,用長鏈接代替頻繁打開關閉的短鏈接、壓縮、重用等等。這些相對比較簡單和好理解,就不多說了。

應用程序層面的事情做到位了之后,我們再來考慮組件層面的優(yōu)化。

/02 組件層面/

組件是指那些非業(yè)務性的東西,比如一些中間件、數(shù)據(jù)庫、運行時的環(huán)境(JVM、WebServer)等。

數(shù)據(jù)庫的調優(yōu),總的來說分為以下三部分:

  • SQL語句。

  • 索引。

  • 連接池。


其它的一些,比如JVM的調優(yōu)最主要的就是對「GC」相關的配置調優(yōu)。WebServer的調優(yōu)主要是針對「連接」相關的調優(yōu)。這些細節(jié)就不贅述了,資料多到看不過來。

/03 系統(tǒng)層面/

系統(tǒng)層面的一些調優(yōu)工作,涉及到運維工程師的一些工作,我不是很擅長就不誤人子弟了。但是我們可以借助系統(tǒng)層面的一些技術指標來觀測并判斷我們的程序是否正常。比如,CPU、線程、網(wǎng)絡、磁盤、內存。

01   CPU

判斷CPU是否正常,大多數(shù)情況下關注這三個指標就夠了,CPU利用率、CPU平均負載、CPU上下文切換。CPU利用率大家基本上都知道,就不多說了,那就說說后面兩個。

關注CPU平均負載的時候,特別需要注意趨勢的變化。如果 1 分鐘/5 分鐘/15 分鐘的三個值相差不大,那說明系統(tǒng)負載很平穩(wěn),則不用關注,如果這三個值逐漸降低,說明負載在漸漸升高,需要排查具體的原因。

CPU上下文切換。 上下文切換的次數(shù)越多,就意味著更多的CPU時間消耗在寄存器、內核棧以及虛擬內存等數(shù)據(jù)的保存和恢復上,真正進行你所期望的運算工作的時間就越少,系統(tǒng)的整體性能自然就會下降。導致這個情況的原因主要有兩點,

  1. 程序內的磁盤I/O、網(wǎng)絡I/O比較多。

     

  2. 程序內啟動的線程過多。


02  線程

線程方面除了關注線程數(shù)之外,還需要關注一下處于「掛起」狀態(tài)的線程數(shù)量有多少。

掛起狀態(tài)的線程數(shù)過多,意味著程序里鎖競爭激烈,需要考慮通過其它的方案來縮小鎖的粒度、級別,甚至是避免用鎖。

03  網(wǎng)絡

通常在硬件層面內網(wǎng)帶寬會遠大于外網(wǎng)的帶寬,所以,外網(wǎng)帶寬被吃滿的情況更加常見,特別是多圖、多流媒體類型的可對外訪問系統(tǒng)。關于流量大小相關的問題一般大家都能想到,就不多說了。

但是,Z哥提醒你 要特別關注端口的使用和每個端口上的連接狀態(tài)情況。比較常見的問題是,連接用完有沒有及時釋放,導致端口被占滿,后續(xù)新的網(wǎng)絡請求無法建立連接通道。(可以通過netstat、ss獲取網(wǎng)絡相關的信息。)

 04  磁盤

除非是規(guī)模非常大的系統(tǒng),否則一般情況下,從磁盤的指標上看不出啥問題。
平時看的時候,除了看看利用率、吞吐量和請求數(shù)量之外,有兩個容易被忽略的點可以多關注下。

第一點,如果I/O利用率很高,但是吞吐量很小,則意味著存在較多的磁盤隨機讀寫,最好把隨機讀寫優(yōu)化成順序讀寫。(可以通過 strace 或者 blktrace 觀察 I/O 是否連續(xù)判斷是否是順序的讀寫行為)

其次,如果I/O等待隊列的長度比較大,則該磁盤存在 I/O 性能問題。一般來說,如果隊列長度持續(xù)超過2就可以這么認為。

05  內存

關注內存的時候除了內存消耗之外,有一個Swap換入和換出的內存大小需要特別注意一下。因為Swap需要讀寫磁盤,所以性能不是很高。如果GC的時候遍歷到的對象恰巧被Swap 出去了,便會有磁盤I/O產生,性能自然會下降。所以這個指標不應該太高。

大多數(shù)內存問題,都和對象常駐內存不及時釋放有關,有很多工具可以觀察對象的內存分配情況。如,jmap、VisualVM、heap dump等。

如果你的程序部署在linux系統(tǒng)上的話,不得不錯過Brendan Gregg的大神整理的精華。下面就引用一張圖,給大家感受一下,具體可以去 http://www.brendangregg.com/linuxperf.html 自行查閱更多相關的內容。

性能優(yōu)化 = 改改代碼?

▲圖片來自于brendangregg.com

最后,雖然性能優(yōu)化是一件大家都知道的好事,但是再好的事做起來都有成本。所以,如非必要,不要過早、過度進行性能優(yōu)化哦。

好了,總結一下。

這篇呢,Z哥和你聊了一下非常讓程序員們頭疼的程序性能問題。想要避免受這個問題困擾的前提是事前做好性能優(yōu)化工作。

做性能優(yōu)化不能走一步算一步。事先需要做三件事 「明確優(yōu)化目的」、「定標準」、「找到瓶頸點」。

具體做優(yōu)化的時候建議 從應用程序層面開始,再到組件層面,最后才是系統(tǒng)層面,從上往下,層層深入。順帶分享了每個層面的常用一些方法和思路。

希望對你有所啟發(fā)。

在一個大系統(tǒng)中,數(shù)據(jù)就像水,整個系統(tǒng)就像是一個漏斗,漏斗的每一層代表每個子程序。上層的子程序對性能的損耗越低,能流下去的水就越多,直到最后一層「數(shù)據(jù)庫」處,也可以理解為是存儲。


所以,趕緊行動起來,開啟保衛(wèi)數(shù)據(jù)庫之戰(zhàn)吧。

推薦閱讀:

  • 8個月打磨,一份送給程序員的「分布式系統(tǒng)」合集

  • 做「容量預估」可沒有true和false

作者: Zachary

出處: https://zacharyfan.com/archives/1051.html


如果你喜歡這篇文章,可以點一下左下角的「  大拇指」。

這樣可以給我一點反饋。: )

謝謝你的舉手之勞。

?關于作者:張帆(Zachary,  個人微信號:Zachary-ZF)。堅持用心打磨每一篇高質量原創(chuàng)。歡迎  掃描下方的二維碼~。

如果你是初級程序員,想提升但不知道如何下手。又或者做程序員多年,陷入了一些瓶頸想拓寬一下視野。歡迎關注我的公眾號「  跨界架構師」,回復「  技術」,送你一份我長期收集和整理的思維導圖。

如果你是運營,面對不斷變化的市場束手無策。又或者想了解主流的運營策略,以豐富自己的“倉庫”。歡迎關注我的公眾號「  跨界架構師」,回復「  運營」,送你一份我長期收集和整理的思維導圖。

定期發(fā)表原創(chuàng)內容:架構設計丨分布式系統(tǒng)丨產品丨運營丨一些深度思考。

性能優(yōu)化 = 改改代碼?


網(wǎng)頁題目:性能優(yōu)化=改改代碼?
網(wǎng)頁地址:http://weahome.cn/article/gpssgd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部