国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

8000字,程序性能優(yōu)化的全能手冊(cè)

這篇具有很好參考價(jià)值的文章主要介紹了8000字,程序性能優(yōu)化的全能手冊(cè)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

8000字講清楚程序性能優(yōu)化。

本文聊一個(gè)程序員都會(huì)關(guān)注的問(wèn)題:性能。

當(dāng)大家談到“性能”時(shí),你首先想到的會(huì)是什么?

  • 是每次請(qǐng)求需要多長(zhǎng)時(shí)間才能返回?
  • 是每秒鐘能夠處理多少次請(qǐng)求?
  • 還是程序的CPU和內(nèi)存使用率高不高?

這些問(wèn)題基本上反應(yīng)了性能關(guān)注的幾個(gè)主要方面:響應(yīng)時(shí)間、吞吐量和資源利用率。在這三個(gè)方面中,如果能夠?qū)崿F(xiàn)更低的響應(yīng)時(shí)間和更高的吞吐量,那么資源利用率也必然得到優(yōu)化。這是因?yàn)槲覀兊墓ぷ骺偸窃谟邢薜挠布?、軟件、時(shí)間和預(yù)算等的約束下進(jìn)行的,而優(yōu)化前兩個(gè)方面將有助于更有效地利用這些資源。

因此,本文將主要圍繞響應(yīng)時(shí)間和吞吐量的優(yōu)化展開(kāi)介紹,包括相關(guān)領(lǐng)域的定義和軟硬件方面的優(yōu)化方法。

響應(yīng)時(shí)間

想象一下,你在餐廳點(diǎn)了一道菜,響應(yīng)時(shí)間就是從你下單到菜品送到你面前的這段時(shí)間。

在計(jì)算機(jī)里,它指的是單次請(qǐng)求或指令處理的時(shí)間。

8000字,程序性能優(yōu)化的全能手冊(cè)

1.1 軟件層面的優(yōu)化

軟件層面的優(yōu)化主要是通過(guò)減少非必要的處理來(lái)降低響應(yīng)時(shí)間,包括減少I(mǎi)O請(qǐng)求和優(yōu)化代碼邏輯。

1.1.1 減少I(mǎi)O請(qǐng)求

減少I(mǎi)O請(qǐng)求的意義

IO就是輸入輸出,減少I(mǎi)O處理就是減少對(duì)輸入輸出設(shè)備的訪(fǎng)問(wèn)。在計(jì)算機(jī)中,除了CPU和內(nèi)存,其它的鍵盤(pán)、鼠標(biāo)、顯示器、音響、硬盤(pán)、網(wǎng)卡等等都屬于輸入輸出設(shè)備。減少對(duì)這些設(shè)備的訪(fǎng)問(wèn)為什么有用呢?

首先讓我們了解下程序的運(yùn)行過(guò)程,大概是這樣的:

操作系統(tǒng)首先將程序的二進(jìn)制指令從硬盤(pán)加載到內(nèi)存,然后再?gòu)膬?nèi)存加載到CPU,然后CPU就按照二進(jìn)制指令的邏輯進(jìn)行處理,指令是加減乘除的就做加減乘除,指令是跳轉(zhuǎn)的就做跳轉(zhuǎn),指令是訪(fǎng)問(wèn)遠(yuǎn)程網(wǎng)絡(luò)的就通過(guò)操作系統(tǒng)+網(wǎng)卡發(fā)起網(wǎng)絡(luò)請(qǐng)求,指令是訪(fǎng)問(wèn)文件的就通過(guò)操作系統(tǒng)+硬盤(pán)進(jìn)行文件讀寫(xiě)。

在CPU的這些處理中,邏輯判斷、跳轉(zhuǎn)、加減乘除都是很快的,因?yàn)樗鼈冎辉贑PU內(nèi)部進(jìn)行處理,CPU中每條指令的運(yùn)行時(shí)間極短;但是如果要進(jìn)行網(wǎng)絡(luò)請(qǐng)求、文件讀寫(xiě),速度就會(huì)大幅下降,這里邊有很多的損耗,包括系統(tǒng)調(diào)用的時(shí)間消耗、總線(xiàn)的傳輸時(shí)間消耗、IO設(shè)備的處理時(shí)間消耗、遠(yuǎn)程過(guò)程的處理時(shí)間消耗等。

我們可以通過(guò)一組數(shù)字直觀感受下,假設(shè)CPU的主頻是1GHZ,執(zhí)行1條指令需要1個(gè)時(shí)鐘周期,那么執(zhí)行1條指令的時(shí)間就是1納秒。而從硬盤(pán)讀取數(shù)據(jù)的時(shí)間消耗要遠(yuǎn)大于此,如果是機(jī)械硬盤(pán),大概在5-20毫秒,百萬(wàn)倍的差距;如果換成固態(tài)硬盤(pán),情況會(huì)好點(diǎn),普遍都在0.1毫秒以下,部分能達(dá)到微秒級(jí),但也是萬(wàn)倍、十萬(wàn)倍以上的差距。

所以減少I(mǎi)O請(qǐng)求能極大的降低響應(yīng)時(shí)間。那么我們可以采取什么方法呢?

硬盤(pán)IO的優(yōu)化

包括降低硬盤(pán)讀寫(xiě)頻次和采用順序讀寫(xiě)。

對(duì)于頻繁使用的數(shù)據(jù),根據(jù)業(yè)務(wù)情況,我們可以把它們放到內(nèi)存中,后續(xù)都從內(nèi)存讀取,速度會(huì)快上不少;對(duì)于需要寫(xiě)入硬盤(pán)的數(shù)據(jù),根據(jù)業(yè)務(wù)情況,我們可以先在內(nèi)存中攢幾條,達(dá)到一定的數(shù)據(jù)量之后再寫(xiě)入硬盤(pán),其實(shí)操作系統(tǒng)本身就會(huì)緩存寫(xiě)入,很多語(yǔ)言寫(xiě)數(shù)據(jù)到硬盤(pán)之后需要做一個(gè)flush的操作,就是用來(lái)實(shí)現(xiàn)最終寫(xiě)入硬盤(pán)的。我們使用Memcached、Redis等都是這個(gè)方案的延伸,只不過(guò)它們被封裝成了獨(dú)立的遠(yuǎn)程服務(wù)。

采用順序讀寫(xiě)主要針對(duì)的是機(jī)械硬盤(pán),因?yàn)闄C(jī)械硬盤(pán)挪動(dòng)懸臂和磁頭比較耗時(shí),順序讀寫(xiě)可以盡量減少機(jī)械移動(dòng)情況的發(fā)生,進(jìn)而提升讀寫(xiě)速度。

網(wǎng)絡(luò)IO的優(yōu)化

網(wǎng)絡(luò)IO的延遲一般都要在毫秒級(jí)以上,對(duì)網(wǎng)絡(luò)IO的優(yōu)化,除了類(lèi)似硬盤(pán)IO優(yōu)化中的的降低IO頻次,另外還可以通過(guò)使用更高效的傳輸協(xié)議、降低數(shù)據(jù)傳輸量等方式進(jìn)行優(yōu)化。

對(duì)于需要頻繁通過(guò)網(wǎng)絡(luò)獲取的數(shù)據(jù),比如訪(fǎng)問(wèn)遠(yuǎn)程服務(wù)、數(shù)據(jù)庫(kù)等獲取的數(shù)據(jù),我們可以在本地內(nèi)存進(jìn)行緩存,訪(fǎng)問(wèn)內(nèi)存比訪(fǎng)問(wèn)網(wǎng)絡(luò)要快很多,只需要選擇合適的緩存存活時(shí)間就好了。

對(duì)于短時(shí)間內(nèi)大量需要通過(guò)網(wǎng)絡(luò)獲取的數(shù)據(jù),我們可以采用批量獲取的方式,比如有一個(gè)列表,列表中的每一條數(shù)據(jù)都要調(diào)用接口去獲取某個(gè)相同的字段,列表有100條數(shù)據(jù)就要請(qǐng)求網(wǎng)絡(luò)100次,如果批量獲取,則只需要一次網(wǎng)絡(luò)請(qǐng)求就把100條數(shù)據(jù)全部拿到,這可以避免大量的網(wǎng)絡(luò)IO時(shí)間消耗,顯著降低業(yè)務(wù)處理的響應(yīng)時(shí)間。

我們一般認(rèn)為http是無(wú)狀態(tài)的,但是它的底層是基于TCP協(xié)議的,這樣每次發(fā)起http請(qǐng)求時(shí),網(wǎng)絡(luò)底層還是要先建立一個(gè)TCP連接,然后本次http請(qǐng)求結(jié)束后再釋放這個(gè)連接。你可能聽(tīng)說(shuō)過(guò)TCP的三次握手、四次揮手、TCP包的順序保證等,這些都需要在客戶(hù)端和服務(wù)器端來(lái)回多次通信才能完成,而且導(dǎo)致http的網(wǎng)絡(luò)請(qǐng)求效率不高。很多大佬也看到了這個(gè)問(wèn)題,所以搞出來(lái)了http2、http3,讓http使用長(zhǎng)連接、跑在UDP協(xié)議上。我們?cè)诰幊虝r(shí)選擇基于http2或者h(yuǎn)ttp3的通信庫(kù)就可以降低網(wǎng)絡(luò)延遲,如果有必要我們也可以直接使用TCP或者UDP編寫(xiě)網(wǎng)絡(luò)程序。

另外如果我們只需要網(wǎng)絡(luò)接口返回的部分?jǐn)?shù)據(jù),就沒(méi)必要傳輸完整的數(shù)據(jù),數(shù)據(jù)在網(wǎng)絡(luò)底層通過(guò)分包、分幀的方式進(jìn)行傳輸,數(shù)據(jù)越大,包、幀的數(shù)量越多,傳輸消耗的時(shí)間也越長(zhǎng)。對(duì)于減少數(shù)據(jù)傳輸量,除了業(yè)務(wù)上的約定,我們也可以通過(guò)一些序列化方式進(jìn)行優(yōu)化,比如采用Protobuf替代JSON通??梢陨筛痰南?nèi)容。

談到Protobuf,不得不提一下gRPC,它使用了Protobuf進(jìn)行序列化處理,還使用了更新的http協(xié)議,根據(jù)我的不嚴(yán)格測(cè)試,同樣的服務(wù),相比HTTP+JSON的方式,gRPC的網(wǎng)絡(luò)延遲可以降低1個(gè)數(shù)量級(jí)。

內(nèi)存IO的優(yōu)化

我們?cè)谏线叺姆治鲋惺前袰PU和內(nèi)存看做一個(gè)整體的,其實(shí)它們內(nèi)部的通信延遲也不可忽視,我們也有一些方法來(lái)優(yōu)化對(duì)內(nèi)存的訪(fǎng)問(wèn),包括下邊一些技術(shù):

零拷貝:這種技術(shù)要解決的問(wèn)題是數(shù)據(jù)在內(nèi)核態(tài)和用戶(hù)態(tài)之間的重復(fù)存放問(wèn)題。

什么是內(nèi)核態(tài)和用戶(hù)態(tài)?操作系統(tǒng)有兩個(gè)主要的功能,一是管理計(jì)算機(jī)上的所有軟件程序,主要是CPU和內(nèi)存資源的分配,二是為一些基礎(chǔ)計(jì)算能力提供統(tǒng)一的使用接口,比如網(wǎng)絡(luò)、硬盤(pán)這種;為了實(shí)現(xiàn)這兩大能力,操作系統(tǒng)就需要有一些管理程序來(lái)處理這些事,這些基礎(chǔ)管理程序就運(yùn)行在內(nèi)核態(tài),而操作系統(tǒng)上的其它程序則運(yùn)行在用戶(hù)態(tài)。同時(shí)基于安全考慮,內(nèi)核態(tài)的程序以及它們使用的資源必須要保護(hù)好,不能隨便訪(fǎng)問(wèn),所以?xún)?nèi)核態(tài)的數(shù)據(jù)就不能讓用戶(hù)態(tài)直接訪(fǎng)問(wèn),用戶(hù)程序訪(fǎng)問(wèn)相關(guān)數(shù)據(jù)時(shí)得先復(fù)制到用戶(hù)態(tài)。

舉個(gè)例子,當(dāng)程序從硬盤(pán)讀取數(shù)據(jù)時(shí),程序先要調(diào)用內(nèi)核程序,內(nèi)核程序再去訪(fǎng)問(wèn)硬盤(pán),此時(shí)數(shù)據(jù)先讀到內(nèi)核內(nèi)存空間中,然后再拷貝到用戶(hù)程序定義的內(nèi)存空間中。如果我們能把用戶(hù)態(tài)和內(nèi)核態(tài)之間的拷貝去掉,就是零拷貝技術(shù)了。

很多語(yǔ)言和框架中都提供了這種零拷貝的能力。比如Java中的Netty框架在發(fā)送文件時(shí),可以直接在內(nèi)核態(tài)將文件數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)端口,而不需要先一點(diǎn)點(diǎn)讀到用戶(hù)態(tài),再一點(diǎn)點(diǎn)寫(xiě)到內(nèi)核態(tài)的網(wǎng)絡(luò)處理程序。

其實(shí)Netty還使用了一些非傳統(tǒng)的零拷貝技術(shù),這包括直接內(nèi)存和復(fù)合緩沖。直接內(nèi)存是Java程序向操作系統(tǒng)直接申請(qǐng)一塊內(nèi)存,這塊內(nèi)存的數(shù)據(jù)可以直接與底層網(wǎng)絡(luò)傳輸進(jìn)行交互,不需要在內(nèi)核態(tài)和用戶(hù)態(tài)之間進(jìn)行拷貝。復(fù)合緩沖是Netty定義了一個(gè)邏輯上的大緩沖區(qū),把網(wǎng)絡(luò)傳輸中的多段小數(shù)據(jù)組合在一起,外部讀取數(shù)據(jù)時(shí)只需要和它打交道,這樣比較優(yōu)雅,實(shí)際也沒(méi)有產(chǎn)生內(nèi)存拷貝。

CPU緩存行:這種技術(shù)主要是充分利用CPU緩存,減少CPU對(duì)內(nèi)存的訪(fǎng)問(wèn)。

什么是CPU緩存?在上邊談到IO設(shè)備的訪(fǎng)問(wèn)時(shí)間時(shí),我們說(shuō)到硬盤(pán)的訪(fǎng)問(wèn)時(shí)間是CPU執(zhí)行單條指令消耗時(shí)間的萬(wàn)倍以上,其實(shí)內(nèi)存的訪(fǎng)問(wèn)時(shí)間相較CPU內(nèi)部也有百倍左右的差距,所以CPU中搞了一個(gè)緩存,將最近需要的數(shù)據(jù)或指令先加載到緩存中,后續(xù)執(zhí)行的時(shí)候都通過(guò)緩存進(jìn)行讀寫(xiě)。緩存與內(nèi)存相比,速度更快,訪(fǎng)問(wèn)一次可能只需要若干納秒,但是成本也更高,數(shù)量比較少,所以沒(méi)有完全代替內(nèi)存。

我們要減少內(nèi)存的訪(fǎng)問(wèn),就需要數(shù)據(jù)在CPU緩存中維持的時(shí)間更久。CPU緩存是以行為基本單位的,如果一行中保存了多個(gè)變量的數(shù)據(jù),它們可能就會(huì)相互影響,比如其中一個(gè)變量更新的頻率很高,這個(gè)緩存行可能就會(huì)頻繁失效,導(dǎo)致和內(nèi)存的頻繁同步,而這個(gè)緩存行中的另一個(gè)變量就受到了連帶影響。解決這個(gè)問(wèn)題可以讓變量獨(dú)占一個(gè)緩存行,比如前后使用一些空位進(jìn)行填充,Java中的Disruptor庫(kù)就是采用了這種方案。

綁定CPU與內(nèi)存:這種技術(shù)主要解決CPU或者內(nèi)核訪(fǎng)問(wèn)不同內(nèi)存時(shí)的速度差異問(wèn)題。

我們知道計(jì)算機(jī)中可以安裝多塊CPU、多條內(nèi)存,在同一塊CPU中也可能存在多個(gè)核心,也就是俗稱(chēng)的多核處理器,這些CPU、核心到每條內(nèi)存的距離可能是不相同的,CPU訪(fǎng)問(wèn)距離近的內(nèi)存,速度就會(huì)快些,訪(fǎng)問(wèn)距離遠(yuǎn)的內(nèi)存,速度就會(huì)慢些。對(duì)于計(jì)算機(jī)的使用者來(lái)說(shuō),我們肯定是希望程序的運(yùn)行速度越快越好,即使做不到最快,也不希望程序時(shí)快時(shí)慢,這樣容易導(dǎo)致?lián)矶隆?/span>

為了解決這個(gè)問(wèn)題,計(jì)算機(jī)發(fā)展出了一種稱(chēng)為NUMA的技術(shù),NUMA的全稱(chēng)是非一致性?xún)?nèi)存訪(fǎng)問(wèn)。在這種技術(shù)中,CPU和內(nèi)存劃分了不同的區(qū)域,CPU訪(fǎng)問(wèn)本區(qū)域的內(nèi)存時(shí)可以直接訪(fǎng)問(wèn),速度十分快;CPU訪(fǎng)問(wèn)其它區(qū)域的內(nèi)存時(shí)需要通過(guò)內(nèi)部的通道,速度會(huì)相對(duì)慢一些。然后操作系統(tǒng)可以感知到NUMA的區(qū)域分布情況,并提供了相應(yīng)的API,讓?xiě)?yīng)用程序可以將自己使用的內(nèi)存和CPU盡量保持在同一個(gè)區(qū)域,或者盡量平均分布在不同的區(qū)域,從而保證了CPU和內(nèi)存之間訪(fǎng)問(wèn)速度。

1.1.2 優(yōu)化代碼邏輯

在我的編程生涯早期,優(yōu)化程序性能時(shí)考慮最多的是:這里是不是可以少些幾行代碼,那里是不是可以不使用循環(huán)。這些固然可以?xún)?yōu)化程序的性能,但是遠(yuǎn)沒(méi)有上邊提到的優(yōu)化IO帶來(lái)的收益大。因?yàn)樯賵?zhí)行幾條代碼只是若干納秒的節(jié)省,而少一次IO則是百倍、千倍、萬(wàn)倍的節(jié)省。不過(guò)當(dāng)IO沒(méi)得優(yōu)化的時(shí)候,我們也不得不考慮在代碼邏輯上下下功夫,特別是一些計(jì)算密集型的程序。

可以從以下幾個(gè)方面著手優(yōu)化:

  • 算法優(yōu)化:選擇更有效率的算法來(lái)減少計(jì)算時(shí)間。例如,使用快速排序代替冒泡排序,數(shù)據(jù)越多,快速排序的算法效率越高,節(jié)省的時(shí)間也越多。
  • 數(shù)據(jù)結(jié)構(gòu)選擇:選擇更合理的數(shù)據(jù)結(jié)構(gòu)。例如,使用哈希表進(jìn)行快速查找,而不是數(shù)組。數(shù)組需要遍歷查找,而Hash表則可以根據(jù)下標(biāo)快速定位。
  • 循環(huán)展開(kāi):將循環(huán)操作改為同樣的邏輯多次執(zhí)行。這個(gè)好處有很多,首先可以減少循環(huán)條件判斷和跳轉(zhuǎn)的處理,然后有利于提高CPU內(nèi)部的指令預(yù)測(cè)準(zhǔn)確度、指令并行度,以及提高CPU緩存的命中率。
  • 延遲計(jì)算:只有在需要結(jié)果的時(shí)候才進(jìn)行計(jì)算,避免不必要的計(jì)算。很多函數(shù)式編程的方法中都大量使用了這一技術(shù),比如C#中針對(duì)列表的LINQ查詢(xún),只有在真的需要處理列表中某條數(shù)據(jù)的時(shí)候才執(zhí)行相應(yīng)的查詢(xún)算法,而不需要提前對(duì)列表中的所有數(shù)據(jù)進(jìn)行處理。在Web前端也有很多的延遲處理方案,比如圖片的懶加載,只在需要顯示圖片的時(shí)候才去加載,對(duì)于圖片比較多的頁(yè)面,可以大幅提升頁(yè)面的加載速度。
  • 異步計(jì)算:程序只處理事務(wù)中的關(guān)鍵部分,然后就給調(diào)用方返回一個(gè)響應(yīng),邊緣事務(wù)或者慢速部分的處理通過(guò)發(fā)送消息的方式,由后臺(tái)其它程序慢慢處理。比如很多的秒殺、搶購(gòu)程序都采用這種方案,先把用戶(hù)的請(qǐng)求收下來(lái),只是發(fā)到一個(gè)待處理的隊(duì)列,然后就給用戶(hù)反饋已經(jīng)收到你的請(qǐng)求、正在處理中;同時(shí)后臺(tái)再有若干程序按照順序處理隊(duì)列中的消息,處理完畢后再給用戶(hù)反饋?zhàn)罱K的結(jié)果。
  • 避免重復(fù)計(jì)算:通過(guò)緩存計(jì)算結(jié)果來(lái)避免重復(fù)執(zhí)行需要花費(fèi)大量時(shí)間的計(jì)算。
  • 并行計(jì)算:利用多線(xiàn)程或多進(jìn)程來(lái)同時(shí)執(zhí)行任務(wù),特別是有多核CPU的時(shí)候。

在進(jìn)行優(yōu)化的時(shí)候,我們也要區(qū)分重點(diǎn),可以先通過(guò)代碼分析工具找到執(zhí)行最頻繁的部分,然后再進(jìn)行優(yōu)化。

1.1.3 使用更好的編譯器

好的編譯器,就像是一流的廚師,能用更少的步驟做出美味的菜。

上邊提到優(yōu)化代碼邏輯時(shí)可以采用“循環(huán)展開(kāi)”的方法,其實(shí)這件事完全可以交給編譯器去做,好的編譯器可以代替人工來(lái)完成這件事,程序員就有更多時(shí)間來(lái)思考業(yè)務(wù)邏輯。

除了“循環(huán)展開(kāi)”,編譯器還可以做“循環(huán)合并”,針對(duì)同一組數(shù)據(jù),如果代碼中編寫(xiě)了多次循環(huán)迭代,并且迭代的方法都是一樣的,編譯器可以將多次迭代合并成一次。

編譯器還可以做很多優(yōu)化,比如移除無(wú)用的代碼、內(nèi)聯(lián)函數(shù)減少壓棧、計(jì)算常量表達(dá)式的值、使用常量替換變量、使用更優(yōu)的算法和數(shù)據(jù)結(jié)構(gòu)、重排程序指令以利于CPU并行執(zhí)行,等等。

不過(guò)大多數(shù)情況下,比如使用Java、.NET時(shí),我們使用官方推薦或者IDE集成的編譯器就足夠了,只有在針對(duì)一些特定計(jì)算平臺(tái)或者特定的領(lǐng)域時(shí),我們才需要進(jìn)行選擇。

1.2 硬件層面的升級(jí)

在硬件層面要縮減程序的運(yùn)行時(shí)間,也就是更換運(yùn)行速度更快的硬件,比如使用主頻更高的CPU,1GHZ的CPU每條指令的執(zhí)行時(shí)間是1納秒,如果更換為3GHZ的CPU,每條指令的執(zhí)行時(shí)間可以降低到0.3納秒。

8000字,程序性能優(yōu)化的全能手冊(cè)

1.2.1 提升CPU性能

提升CPU就像是給餐廳請(qǐng)一個(gè)更快的廚師,他做菜的速度更快。

提升主頻:上邊我們已經(jīng)說(shuō)過(guò),提升主頻可以降低每條指令的執(zhí)行時(shí)間。但是主頻的提升不是無(wú)限的,因?yàn)橹黝l越高,電子元器件的散熱、穩(wěn)定性、成本等都會(huì)成為新的問(wèn)題,所以必須在這其中進(jìn)行平衡。

指令并行技術(shù):現(xiàn)代CPU中已經(jīng)產(chǎn)生了很多并行執(zhí)行指令的技術(shù),包括亂序執(zhí)行、分支預(yù)測(cè)技術(shù)、超標(biāo)量技術(shù)、多發(fā)射技術(shù)等,這些都像是廚師在同時(shí)處理多個(gè)菜品,而不是一個(gè)個(gè)來(lái),這自然能降低整體的響應(yīng)時(shí)間,當(dāng)然CPU肯定也要兼顧邏輯順序。

CPU緩存:現(xiàn)代CPU中很大一塊面積都是用來(lái)放置CPU緩存的,上文在【內(nèi)存的IO優(yōu)化】中我們提到過(guò)使用CPU緩存可以大幅降低CPU讀取指令的時(shí)間消耗,同時(shí)我們還需要注意到CPU存在多個(gè)核心時(shí),數(shù)據(jù)可能會(huì)被加載到不同的核心緩存中,數(shù)據(jù)在不同緩存中的同步也是一項(xiàng)很有挑戰(zhàn)的工作,因此足夠大的CPU緩存和足夠好的CPU緩存更新機(jī)制,對(duì)于降低響應(yīng)時(shí)間也很關(guān)鍵。

增加核心:主頻無(wú)法大幅提升時(shí),可以在CPU中多增加幾個(gè)核心,每個(gè)核心就是一個(gè)獨(dú)立的處理器,不同的線(xiàn)程、進(jìn)程可以并行運(yùn)行在不同的核心上,這樣也可以降低爭(zhēng)搶?zhuān)⑿卸仍礁?,程序的?zhí)行時(shí)間相對(duì)也越低。

我們?cè)谶x擇CPU時(shí),應(yīng)該結(jié)合業(yè)務(wù)特點(diǎn),綜合考慮以上這些方面。

1.2.2 跳過(guò)CPU的技術(shù)

理論上,計(jì)算機(jī)中所有的計(jì)算都是CPU來(lái)處理的,不過(guò)我們也可以讓它只處理最重要的事,一些不太重要的事就授權(quán)給其它部件處理,就像廚房中洗菜、切菜這些事都交給小工去處理,大廚專(zhuān)注于炒菜,可以讓出菜的速度更快。

在計(jì)算中有一種DMA技術(shù)就是干這個(gè)事的,比如使用支持DMA的網(wǎng)卡時(shí),網(wǎng)卡可以將數(shù)據(jù)直接寫(xiě)入到一塊內(nèi)存區(qū)域,等寫(xiě)滿(mǎn)了再通知CPU來(lái)讀取,而不是讓CPU一開(kāi)始就從網(wǎng)卡一點(diǎn)點(diǎn)讀取,這會(huì)大幅提高網(wǎng)絡(luò)數(shù)據(jù)處理的效率。因?yàn)榫W(wǎng)卡的速度相對(duì)CPU要慢的多,沒(méi)必要在這里耗著,等數(shù)據(jù)接收到內(nèi)存之后,CPU再和內(nèi)存打交道,速度就會(huì)快很多了。

對(duì)于需要集成IO設(shè)備進(jìn)行處理的程序,我們可以盡量選擇支持DMA技術(shù)的硬件。

1.2.3 使用專(zhuān)用硬件

這個(gè)就像做飯時(shí)使用不同的廚具,雖然我們也可以在湯鍋里炒菜,但是總不如炒鍋用的順手,用的順手就可以做到更快的速度。

在計(jì)算機(jī)中CPU是一種通用計(jì)算器,它可以進(jìn)行各種運(yùn)算,但是通用也有通用的壞處,那就是干一些事的時(shí)候效率不高,比如圖像處理、深度學(xué)習(xí)算法的運(yùn)算,這些運(yùn)算的特點(diǎn)就是包含大量的向量計(jì)算,CPU執(zhí)行向量運(yùn)算的效率比較低。

為了加速圖像處理,科技工作者們搞出了GPU,效率有了很大的提升,計(jì)算速度飛起。GPU一開(kāi)始是專(zhuān)門(mén)用于圖形計(jì)算的,圖形計(jì)算的主要工作就是向量運(yùn)算,而深度學(xué)習(xí)也主要是向量計(jì)算,所以GPU后來(lái)也被大量用于深度學(xué)習(xí)。再到后來(lái),科技工作者又搞出來(lái)了TPU,這種設(shè)備更加有利于深度學(xué)習(xí)的計(jì)算。

另外針對(duì)一些需要頻繁讀寫(xiě)硬盤(pán)的程序,比如數(shù)據(jù)庫(kù)程序,我們也推薦使用固態(tài)硬盤(pán)代替機(jī)械硬盤(pán),因?yàn)楣虘B(tài)硬盤(pán)的訪(fǎng)問(wèn)延遲相比機(jī)械硬盤(pán)會(huì)低1個(gè)或多個(gè)數(shù)量級(jí),這會(huì)大幅降低數(shù)據(jù)讀寫(xiě)的延遲。

所以針對(duì)不同的計(jì)算特點(diǎn),我們可以選擇更專(zhuān)用的硬件來(lái)加速程序的處理,這是個(gè)不錯(cuò)的方案。

---

當(dāng)然使用性能更高的硬件,需要付出更多的成本,需要仔細(xì)評(píng)估。以前技術(shù)開(kāi)發(fā)領(lǐng)域流傳過(guò)有一句話(huà):不要對(duì)程序做過(guò)多的優(yōu)化,升級(jí)下硬件就行了。這是因?yàn)楫?dāng)時(shí)升級(jí)硬件的成本要遠(yuǎn)低于優(yōu)化程序的時(shí)間成本,不過(guò)隨著互聯(lián)網(wǎng)的發(fā)展,人們對(duì)性能的追求越來(lái)越高,升級(jí)硬件的難度和成本也越來(lái)越高,這句話(huà)變得不是那么可靠。從Go、Rust等語(yǔ)言的流行,Java、.NET等對(duì)原生編譯的支持,我們也可以感受到這個(gè)趨勢(shì),硬件資源開(kāi)始變得稀缺了。

吞吐量

吞吐量就像餐廳一天能服務(wù)多少客人。

在計(jì)算機(jī)里,它指的是單位時(shí)間內(nèi)處理的請(qǐng)求數(shù)、數(shù)據(jù)量或執(zhí)行的指令數(shù)。

8000字,程序性能優(yōu)化的全能手冊(cè)

2.1 縮短響應(yīng)時(shí)間

縮短響應(yīng)時(shí)間自然能提高吞吐量,就像提高廚師做菜速度能讓更多客人吃到菜一樣。

上文已經(jīng)介紹了響應(yīng)時(shí)間的很多優(yōu)化方法,這里及不重復(fù)了。

但是響應(yīng)時(shí)間對(duì)吞吐量的影響不一定總是正面的。降低響應(yīng)時(shí)間有可能會(huì)增加資源的使用,比如我們把原本放在硬盤(pán)中的數(shù)據(jù)都放到了內(nèi)存中,然后就沒(méi)有足夠的內(nèi)存用來(lái)創(chuàng)建新的線(xiàn)程,服務(wù)器就無(wú)法接收更多的請(qǐng)求,吞吐量也就無(wú)法提升。

2.2 增加并發(fā)能力

2.2.3 增加資源

這是最直接的方法,就像買(mǎi)更多的爐子和鍋,就能同時(shí)做更多的菜。

在計(jì)算機(jī)領(lǐng)域,我們可以購(gòu)買(mǎi)更多的服務(wù)器、更強(qiáng)勁的CPU或GPU、更大的內(nèi)存、讀寫(xiě)能力更強(qiáng)的IO設(shè)備、更大的網(wǎng)絡(luò)帶寬,等等。這些可以讓程序在單位時(shí)間內(nèi)接收更多的請(qǐng)求、以及更大的并發(fā)處理能力,也就增加了系統(tǒng)的吞吐量。當(dāng)然在具體的增加某種資源之前,我們需要先找到系統(tǒng)的瓶頸,比如內(nèi)存使用經(jīng)常達(dá)到90%,我們就增加內(nèi)存空間。

需要注意,增加資源雖然可以提升系統(tǒng)的吞吐量,但是這也會(huì)有一個(gè)臨界點(diǎn),越過(guò)這個(gè)臨界點(diǎn)之后,獲得的收益將會(huì)低于為此增加的資源成本,所以我們應(yīng)該仔細(xì)評(píng)估收益和成本,再?zèng)Q定增加多少資源。

同時(shí)本著節(jié)約的精神,我們應(yīng)該追求使用更少的資源來(lái)完成更多的工作,這樣也能產(chǎn)生更多的收益。

2.2.2 利用CPU的先進(jìn)技術(shù)

上文我們?cè)凇?.2.1 提升CPU性能】中已經(jīng)提到過(guò)CPU的指令并行技術(shù),包括流水線(xiàn)、分支預(yù)測(cè)、亂序執(zhí)行、多發(fā)射、超標(biāo)量等,它們可以讓CPU同時(shí)執(zhí)行多條指令,提升CPU的指令吞吐量,自然也就提升了程序的處理吞吐量。

這些都是CPU內(nèi)部的技術(shù)優(yōu)化,只要購(gòu)買(mǎi)性能優(yōu)良的CPU,我們就可以擁有這些能力;同時(shí)我們?cè)诰幊虝r(shí)也可以盡量觸發(fā)指令的并行執(zhí)行,比如上文【1.1.2 優(yōu)化代碼邏輯】中提到的循環(huán)展開(kāi)、內(nèi)聯(lián)函數(shù)等,當(dāng)然我更推薦選擇一個(gè)更好的編譯器來(lái)完成這些優(yōu)化工作,程序員應(yīng)該多思考下怎么運(yùn)用技術(shù)滿(mǎn)足業(yè)務(wù)需求。

除了CPU微觀層面的優(yōu)化,我們還可以利用下CPU的多核并行能力,在程序中使用多線(xiàn)程、多進(jìn)程,讓程序并行處理,從而提升程序的業(yè)務(wù)吞吐量。

CPU的這些能力就像是多個(gè)廚師協(xié)作,同時(shí)準(zhǔn)備不同的菜品,就能在單位時(shí)間內(nèi)把更多的菜品端上桌。

2.2.1 提高資源利用率

大家可能聽(tīng)說(shuō)過(guò)Go的并發(fā)能力特別強(qiáng),簡(jiǎn)單手?jǐn)]一個(gè)服務(wù)就能輕松應(yīng)對(duì)百萬(wàn)并發(fā),原因就是因?yàn)镚o搞出了協(xié)程。那么協(xié)程為什么這么優(yōu)秀呢?

這是因?yàn)槌绦蚴褂脗鹘y(tǒng)的線(xiàn)程模型時(shí),線(xiàn)程消耗的時(shí)間和空間成本比較高,時(shí)間成本就是CPU的使用時(shí)間,空間成本就是內(nèi)存占用,要提升吞吐量只能增加更多的CPU和內(nèi)存資源,資源利用率高不起來(lái),具體是怎么回事呢?

首先看我們編寫(xiě)的業(yè)務(wù)程序,其實(shí)大部分工作都是很多IO操作,比如訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)、請(qǐng)求網(wǎng)絡(luò)接口、讀寫(xiě)文件等,這些IO操作相比CPU指令操作慢了4、5個(gè)數(shù)量級(jí)。使用線(xiàn)程模型時(shí),發(fā)起IO請(qǐng)求后,當(dāng)前線(xiàn)程使用的CPU要么等著要么切換給其它線(xiàn)程使用,等著CPU就是空轉(zhuǎn),切換給其它線(xiàn)程時(shí)的成本也比較高,總之就是浪費(fèi)了CPU時(shí)間;另外在等待IO返回的這段時(shí)間內(nèi),線(xiàn)程不會(huì)消失,會(huì)一直存在,而線(xiàn)程占用的內(nèi)存比較大(Windows默認(rèn)1M,Linux默認(rèn)8M),妥妥的站著什么不拉什么。這就是線(xiàn)程的時(shí)間成本和空間成本問(wèn)題。

解決這個(gè)問(wèn)題的第一步是使用異步編程:IO操作提交后,就把線(xiàn)程釋放掉,程序也不用在這里等著,等IO返回結(jié)果時(shí),操作系統(tǒng)再分配一個(gè)新的線(xiàn)程進(jìn)行處理。線(xiàn)程少了,CPU等待、切換和內(nèi)存占用也就少了,計(jì)算資源自然就可以支持更多的請(qǐng)求了,吞吐量也就上來(lái)了。這就像是廚師在等待一個(gè)菜烤制的同時(shí),可以去炒另一道菜。

協(xié)程則是在異步的基礎(chǔ)上更進(jìn)一步,把程序執(zhí)行的最小單位由線(xiàn)程變成了協(xié)程,協(xié)程分配的內(nèi)存更小,初始時(shí)僅為2KB,不過(guò)它可以隨著任務(wù)執(zhí)行按需增長(zhǎng),最大可達(dá)1GB。同樣的8M內(nèi)存,Linux中只能創(chuàng)建1個(gè)線(xiàn)程,而協(xié)程最多則可以創(chuàng)建4096個(gè)。我們也就能夠理解Go的并發(fā)能力為什么這么強(qiáng)了。


總結(jié)

性能優(yōu)化是一個(gè)復(fù)雜且多面的話(huà)題,涉及到代碼的編寫(xiě)、系統(tǒng)的架構(gòu)以及硬件的選擇與配置。在追求性能的旅途中,我們需要掌握的知識(shí)有很多,既有軟件方面的,也有硬件方面的,很多東西我也沒(méi)有展開(kāi)詳細(xì)講,只是給大家提供了一個(gè)引子,遇到問(wèn)題的時(shí)候可以順著它去尋找。

在優(yōu)化過(guò)程中,還需要注意性能的提升并非總是線(xiàn)性的,我們應(yīng)當(dāng)找到系統(tǒng)的瓶頸點(diǎn),有針對(duì)性地優(yōu)化,并在資源成本和性能收益之間做出平衡。優(yōu)化的最終目的是在有限的資源下,盡可能地提升程序的響應(yīng)速度和處理能力。

關(guān)注螢火架構(gòu),加速技術(shù)提升!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-776866.html

到了這里,關(guān)于8000字,程序性能優(yōu)化的全能手冊(cè)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • uniapp小程序如何進(jìn)行性能優(yōu)化

    減少頁(yè)面層級(jí):盡量減少頁(yè)面的層級(jí),減少頁(yè)面的嵌套,可以減少頁(yè)面的渲染時(shí)間,提高頁(yè)面的加載速度。 避免過(guò)多的數(shù)據(jù)綁定:減少數(shù)據(jù)綁定的次數(shù),盡量將數(shù)據(jù)綁定到最外層的組件上,避免過(guò)多的數(shù)據(jù)綁定,可以減少頁(yè)面的渲染時(shí)間。 避免頻繁的數(shù)據(jù)更新:對(duì)于一些不

    2024年02月13日
    瀏覽(50)
  • android開(kāi)發(fā)實(shí)戰(zhàn)經(jīng)典,設(shè)計(jì)思想與代碼質(zhì)量?jī)?yōu)化+程序性能優(yōu)化+開(kāi)發(fā)效率優(yōu)化

    android開(kāi)發(fā)實(shí)戰(zhàn)經(jīng)典,設(shè)計(jì)思想與代碼質(zhì)量?jī)?yōu)化+程序性能優(yōu)化+開(kāi)發(fā)效率優(yōu)化

    一、關(guān)于Handler面試那些問(wèn)題 1、Handler Looper Message 關(guān)系是什么? 2、Messagequeue 的數(shù)據(jù)結(jié)構(gòu)是什么?為什么要用這個(gè)數(shù) 據(jù)結(jié)構(gòu)? 3、如何在子線(xiàn)程中創(chuàng)建 Handler? 4、Handler post 方法原理? 5、Android 消息機(jī)制的原理及源碼解析 6、Android Handler 消息機(jī)制 7、Android 消息機(jī)制 … 二、關(guān)于

    2024年03月11日
    瀏覽(102)
  • 異步I/O優(yōu)化Python代理程序性能

    異步I/O優(yōu)化Python代理程序性能

    作為一名爬蟲(chóng)程序員,你是否曾經(jīng)遇到過(guò)需要處理大量網(wǎng)絡(luò)請(qǐng)求的情況?你是否想要提高你的Python代理程序的性能,讓它更快、更高效?別擔(dān)心,我來(lái)給你分享一些關(guān)于異步I/O如何優(yōu)化Python代理程序性能的實(shí)用知識(shí)。 首先,讓我們來(lái)了解一下什么是異步I/O。在傳統(tǒng)的同步I/

    2024年02月11日
    瀏覽(27)
  • Rust 性能優(yōu)化 : Rust 性能優(yōu)化技巧,提升 Rust 程序的執(zhí)行效率和資源利用率 The Rust Performance

    作者:禪與計(jì)算機(jī)程序設(shè)計(jì)藝術(shù) 在過(guò)去的幾年中,隨著編程語(yǔ)言的快速發(fā)展,編程人員已經(jīng)逐漸從依賴(lài)編譯型語(yǔ)言轉(zhuǎn)向了使用解釋型語(yǔ)言。相對(duì)于編譯型語(yǔ)言來(lái)說(shuō),解釋型語(yǔ)言具有更快的執(zhí)行速度,在某些情況下甚至可以實(shí)現(xiàn)接近編譯器的運(yùn)行時(shí)效率。但是另一方面,這些語(yǔ)

    2024年02月07日
    瀏覽(303)
  • Golang 程序性能優(yōu)化利器 PGO 詳解(一):簡(jiǎn)單介紹及使用

    在軟件開(kāi)發(fā)過(guò)程中,性能優(yōu)化是不可或缺的一部分。無(wú)論是在Web服務(wù)、數(shù)據(jù)處理系統(tǒng)還是實(shí)時(shí)通信中,良好的性能都是至關(guān)重要的。Golang 從1.20版版本開(kāi)始引入的?Profile Guided Optimization(PGO)機(jī)制能夠幫助更好地優(yōu)化 Go 程序的性能。 編譯器在編譯程序的時(shí)候會(huì)對(duì)程序做很多優(yōu)

    2024年02月13日
    瀏覽(19)
  • 如何調(diào)試移動(dòng)應(yīng)用程序數(shù)據(jù)庫(kù)問(wèn)題并優(yōu)化數(shù)據(jù)存儲(chǔ)性能

    在移動(dòng)應(yīng)用開(kāi)發(fā)的動(dòng)態(tài)領(lǐng)域中,無(wú)缺陷的用戶(hù)體驗(yàn)是最終目標(biāo)。然而,在表面下隱藏著一個(gè)復(fù)雜的數(shù)據(jù)存儲(chǔ)和檢索網(wǎng)絡(luò)。當(dāng)數(shù)據(jù)庫(kù)問(wèn)題出現(xiàn)時(shí),它們可能會(huì)干擾甚至最精心設(shè)計(jì)的應(yīng)用程序。這就是為什么了解如何調(diào)試移動(dòng)應(yīng)用程序數(shù)據(jù)庫(kù)問(wèn)題和優(yōu)化數(shù)據(jù)存儲(chǔ)性能對(duì)于追求卓越

    2024年02月13日
    瀏覽(30)
  • JVM逃逸分析原理解析:優(yōu)化Java程序性能和內(nèi)存利用效率

    在Java開(kāi)發(fā)中,性能和內(nèi)存利用效率一直是開(kāi)發(fā)者關(guān)注的焦點(diǎn)。為了提高Java程序的執(zhí)行效率,JVM引入了逃逸分析技術(shù)。本文將詳細(xì)解析JVM逃逸分析的原理,幫助讀者深入理解其工作機(jī)制。 逃逸分析是一種用于確定對(duì)象在方法的生命周期內(nèi)是否逃逸出方法外部范圍的技術(shù)。在

    2024年01月20日
    瀏覽(87)
  • Golang 程序性能優(yōu)化利器 PGO 詳解(二):收集樣本數(shù)據(jù)和編譯

    在軟件開(kāi)發(fā)過(guò)程中,性能優(yōu)化是不可或缺的一部分。無(wú)論是在Web服務(wù)、數(shù)據(jù)處理系統(tǒng)還是實(shí)時(shí)通信中,良好的性能都是至關(guān)重要的。Golang 從1.20版版本開(kāi)始引入的 Profile Guided Optimization(PGO)機(jī)制能夠幫助更好地優(yōu)化 Go 程序的性能。 上篇文章講解了 Golang PGO 的概念和使用方法

    2024年02月12日
    瀏覽(18)
  • 性能優(yōu)化2.0,新增緩存后,程序的秒開(kāi)率不升反降

    性能優(yōu)化2.0,新增緩存后,程序的秒開(kāi)率不升反降

    大家好,我是哪吒。 在上一篇文章中提到,有一個(gè)頁(yè)面加載速度很慢,是通過(guò)緩沖流優(yōu)化的。 查詢(xún)的時(shí)候,會(huì)訪(fǎng)問(wèn)后臺(tái)數(shù)據(jù)庫(kù),查詢(xún)前20條數(shù)據(jù),按道理來(lái)說(shuō),這應(yīng)該很快才對(duì)。 追蹤代碼,看看啥問(wèn)題,最后發(fā)現(xiàn)問(wèn)題有三: 表中有一個(gè)BLOB大字段,存儲(chǔ)著一個(gè)PDF模板,也就是

    2024年01月16日
    瀏覽(18)
  • Linux C++性能優(yōu)化秘籍:從編譯器到代碼,探究高性能C++程序的實(shí)現(xiàn)之道

    Linux C++性能優(yōu)化秘籍:從編譯器到代碼,探究高性能C++程序的實(shí)現(xiàn)之道

    隨著大數(shù)據(jù)、人工智能等技術(shù)的飛速發(fā)展,程序性能優(yōu)化的重要性愈發(fā)突出。優(yōu)化性能可以降低資源消耗、提高系統(tǒng)響應(yīng)速度,從而在有限的硬件資源下,實(shí)現(xiàn)更高的吞吐量和處理能力。此外,性能優(yōu)化也有助于降低能耗、減少散熱問(wèn)題,延長(zhǎng)硬件使用壽命。 Linux操作系統(tǒng)具

    2023年04月09日
    瀏覽(47)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包