【面經(jīng)】面試官:做過(guò)性能優(yōu)化的工作嗎?你會(huì)從哪些方面入手做性能優(yōu)化呢?
作者個(gè)人研發(fā)的在高并發(fā)場(chǎng)景下,提供的簡(jiǎn)單、穩(wěn)定、可擴(kuò)展的延遲消息隊(duì)列框架,具有精準(zhǔn)的定時(shí)任務(wù)和延遲隊(duì)列處理功能。自開(kāi)源半年多以來(lái),已成功為十幾家中小型企業(yè)提供了精準(zhǔn)定時(shí)調(diào)度方案,經(jīng)受住了生產(chǎn)環(huán)境的考驗(yàn)。為使更多童鞋受益,現(xiàn)給出開(kāi)源框架地址:https://github.com/sunshinelyz/mykit-delay
寫(xiě)在前面
隨著互聯(lián)網(wǎng)的高速發(fā)展,互聯(lián)網(wǎng)行業(yè)已經(jīng)從IT時(shí)代慢慢步入到DT時(shí)代。對(duì)于Java程序員的要求越來(lái)越高,只是單純的掌握CRUD不足以勝任互聯(lián)網(wǎng)公司的相關(guān)職位,大量招聘崗位顯示:如果是面試中高級(jí)的Java崗,基本上都需要懂性能優(yōu)化的相關(guān)知識(shí)。今天,我們就一起來(lái)聊聊一個(gè)經(jīng)典的面試題:做過(guò)性能優(yōu)化的工作嗎?你會(huì)從哪些方面入手做性能優(yōu)化呢?
問(wèn)題分析
標(biāo)題中問(wèn)出了兩個(gè)問(wèn)題,一個(gè)是有沒(méi)有做過(guò)性能優(yōu)化的工作,一個(gè)是從哪些方面入手做性能優(yōu)化。對(duì)于第一個(gè)問(wèn)題,我們可以直接回答有或者沒(méi)有。相信小伙伴們都希望自己做過(guò)性能優(yōu)化的工作,如果是回答做過(guò),那第二個(gè)問(wèn)題,我們又該如何回答呢?
首先,對(duì)于第二個(gè)問(wèn)題來(lái)說(shuō),問(wèn)的是會(huì)從哪些方面入手。這個(gè)問(wèn)題就沒(méi)有固定答案了。你可以按照你以往的經(jīng)驗(yàn)來(lái)回答這個(gè)問(wèn)題,但是,在回答這個(gè)問(wèn)題之前,需要先好好梳理下你的思路,將你要表達(dá)的說(shuō)清楚。
接下來(lái),我們就一起來(lái)聊聊第二個(gè)問(wèn)題:你會(huì)從哪些方面入手做性能優(yōu)化?
我們可以從性能優(yōu)化的幾個(gè)方面來(lái)進(jìn)行回答。下面,我們就來(lái)聊聊性能優(yōu)化可以從哪些方面進(jìn)行。
性能優(yōu)化有哪些方面?
這里,我結(jié)合平時(shí)工作中的總結(jié),將性能優(yōu)化總結(jié)為下面這張圖。
也就是說(shuō),我們可以從數(shù)據(jù)聚合優(yōu)化、資源沖突優(yōu)化、算法優(yōu)化、JVM優(yōu)化、復(fù)用優(yōu)化、計(jì)算優(yōu)化和快速實(shí)現(xiàn)等方面來(lái)進(jìn)行回答。接下來(lái),我們就針對(duì)每個(gè)點(diǎn)進(jìn)行說(shuō)明。
數(shù)據(jù)聚合優(yōu)化
數(shù)據(jù)聚合優(yōu)化主要針對(duì)的是對(duì)于數(shù)據(jù)的整合和傳輸?shù)膬?yōu)化。比如:我們從數(shù)據(jù)庫(kù)中查詢(xún)出的數(shù)據(jù),經(jīng)過(guò)程序的聚合處理后再返回給客戶(hù)端,而不用客戶(hù)端調(diào)用多次接口來(lái)分別獲取數(shù)據(jù)。
再比如:我們?cè)陧?xiàng)目中使用的Nginx,一般都會(huì)開(kāi)啟GZIP壓縮,使傳輸?shù)臄?shù)據(jù)更加緊湊,同時(shí),使傳輸?shù)臄?shù)據(jù)量更小。
細(xì)心的小伙伴會(huì)發(fā)現(xiàn),我們對(duì)于數(shù)據(jù)聚合的優(yōu)化,主要是使傳輸?shù)臄?shù)據(jù)量更小。所以,我們?cè)谑褂肧QL語(yǔ)句查詢(xún)數(shù)據(jù)庫(kù)中的數(shù)據(jù)時(shí),盡量查詢(xún)那些需要的字段,對(duì)于不需要的字段就直接忽略不查詢(xún)了,避免在SQL語(yǔ)句中出現(xiàn)select *
資源沖突優(yōu)化
在我們平時(shí)的工作中,尤其是在高并發(fā)的場(chǎng)景下,經(jīng)常會(huì)出現(xiàn)鎖沖突的問(wèn)題,鎖沖突是資源沖突的一個(gè)典型場(chǎng)景。
關(guān)于鎖我們可以聯(lián)想到數(shù)據(jù)庫(kù)的行鎖、表鎖、Java中的synchronized和Lock等。如果對(duì)應(yīng)到操作系統(tǒng)級(jí)別,則會(huì)有CPU命令級(jí)別的鎖,JVM指令級(jí)別的鎖,操作系統(tǒng)的內(nèi)部鎖等。
這里,小伙伴們需要注意一點(diǎn):只有在并發(fā)的場(chǎng)景下,才會(huì)出現(xiàn)資源沖突的問(wèn)題。也就是說(shuō):在同一時(shí)刻,只能有一個(gè)請(qǐng)求獲取到請(qǐng)求資源,解決沖突的方式就是加鎖。
算法優(yōu)化
在一個(gè)大型的互聯(lián)網(wǎng)項(xiàng)目中,往往涉及到分布式和微服務(wù)等技術(shù),其中,也會(huì)使用到大量的數(shù)據(jù)結(jié)構(gòu)和算法,對(duì)于算法的優(yōu)化能夠顯著的提高系統(tǒng)的性能。一個(gè)好的實(shí)現(xiàn),相比于一個(gè)拙劣的實(shí)現(xiàn)來(lái)說(shuō),在系統(tǒng)性能的提升上存在著巨大的差異。
比如,作為 List 的實(shí)現(xiàn),LinkedList 和 ArrayList 在隨機(jī)訪(fǎng)問(wèn)的性能上,差了好幾個(gè)數(shù)量級(jí);又比如,CopyOnWriteList 采用寫(xiě)時(shí)復(fù)制的方式,可以顯著降低讀多寫(xiě)少場(chǎng)景下的鎖沖突。而什么時(shí)候使用同步,什么時(shí)候是線(xiàn)程安全的,也對(duì)我們的編碼能力有較高的要求。
所以,我們需要在平時(shí)工作過(guò)程中,多多積累數(shù)據(jù)結(jié)構(gòu)和算法的相關(guān)知識(shí)。
JVM優(yōu)化
JVM調(diào)優(yōu),不用說(shuō),這是每個(gè)Java工程師必須要掌握的標(biāo)準(zhǔn)技能。所有的Java程序最終都是運(yùn)行在JVM中的,對(duì)JVM進(jìn)行優(yōu)化也能夠提升Java程序的性能。但是,需要注意的是:如果在優(yōu)化JVM時(shí),參數(shù)設(shè)置不當(dāng),可能會(huì)造成內(nèi)存溢出等嚴(yán)重的問(wèn)題。
目前被廣泛使用的垃圾回收器是 G1,通過(guò)很少的參數(shù)配置,內(nèi)存即可高效回收。CMS 垃圾回收器已經(jīng)在 Java 14 中被移除,由于它的 GC 時(shí)間不可控,有條件應(yīng)該盡量避免使用。
復(fù)用優(yōu)化
復(fù)用優(yōu)化,這個(gè)看名字就知道,說(shuō)白了就是可以重復(fù)利用。估計(jì)很多小伙伴都有這樣的經(jīng)驗(yàn),在寫(xiě)代碼的時(shí)候,可以將很多重復(fù)的代碼抽象出來(lái),做成公共的方法。這樣,就不用每次都去寫(xiě)重復(fù)的邏輯代碼了。這是代碼層面的復(fù)用。
如果是數(shù)據(jù)層面的話(huà),我們可以使用緩沖和緩存來(lái)復(fù)用數(shù)據(jù)。
這里,小伙伴們需要注意一個(gè)知識(shí)點(diǎn):緩沖主要針對(duì)的是寫(xiě)操作,緩存主要針對(duì)的是讀操作。
另一個(gè)復(fù)用優(yōu)化的典型場(chǎng)景就是池化技術(shù),比如:數(shù)據(jù)庫(kù)連接池、線(xiàn)程池等。
計(jì)算優(yōu)化
對(duì)于計(jì)算優(yōu)化來(lái)說(shuō),我們可以從以下幾個(gè)小的方面來(lái)闡述。
并行計(jì)算
不難理解,就是多個(gè)計(jì)算同時(shí)進(jìn)行。這里,又可以將并行計(jì)算分為:多機(jī)并行計(jì)算、多進(jìn)程并行計(jì)算和多線(xiàn)程并行計(jì)算。
多機(jī)并行計(jì)算: 將一個(gè)大的計(jì)算任務(wù),拆分成N個(gè)小的計(jì)算任務(wù),分發(fā)到不同的機(jī)器進(jìn)行處理。典型的場(chǎng)景就是Hadoop的MapReduce極端。
多進(jìn)程計(jì)算: 比如,Nginx采用的NIO模型,采用的是進(jìn)程調(diào)度的策略,由Master進(jìn)程調(diào)度Worker進(jìn)程,Worker進(jìn)行來(lái)處理具體的請(qǐng)求。
多線(xiàn)程計(jì)算:對(duì)于多線(xiàn)程計(jì)算來(lái)說(shuō),也是我們平時(shí)接觸最多的一種計(jì)算方式,我們可以使用多線(xiàn)程技術(shù),將復(fù)雜的邏輯計(jì)算拆分成一個(gè)個(gè)小的計(jì)算任務(wù),分發(fā)到不同的線(xiàn)程中去執(zhí)行。
同步變異步
同步和異步的區(qū)別就是:同步需要等待返回結(jié)果,異步不需要等待返回結(jié)果。如果我們?cè)跇I(yè)務(wù)程序中,不需要等待返回結(jié)果數(shù)據(jù),則我們可以將同步調(diào)用優(yōu)化為異步調(diào)用,從而提升我們系統(tǒng)的性能。
懶加載
最典型的場(chǎng)景就是Spring中的懶加載,只有第一次獲取bean的時(shí)候,才會(huì)創(chuàng)建bean實(shí)例。
快速實(shí)現(xiàn)
對(duì)于快速實(shí)現(xiàn)來(lái)說(shuō),不僅包含我們需要利用相關(guān)的程序框架迅速開(kāi)發(fā)出我們想要的業(yè)務(wù),也需要我們?cè)谶M(jìn)行技術(shù)選型時(shí),盡量使用一些性能優(yōu)良的組件。比如,在進(jìn)行網(wǎng)絡(luò)開(kāi)發(fā)時(shí),盡量選擇Netty,結(jié)合輕量級(jí)的數(shù)據(jù)傳輸,就不要使用WebService等技術(shù)了。
很多公司喜歡使用適配器模式,在一些現(xiàn)有的開(kāi)源組件之上,再抽象一層自己的組件,這樣就能夠做到切換底層組件的時(shí)候,對(duì)上層應(yīng)用無(wú)感。
本文轉(zhuǎn)載自微信公眾號(hào)「冰河技術(shù)」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系冰河技術(shù)公眾號(hào)。
































