自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊軟件性能優(yōu)化全景

開發(fā) 架構
性能優(yōu)化是指在不影響正確性的前提下,使程序運行得更快,它是一個非常廣泛的話題。

[[361266]]

本文轉載自微信公眾號「碼磚雜役」,作者我不想種地。轉載本文請聯(lián)系碼磚雜役公眾號。  

性能優(yōu)化是指在不影響正確性的前提下,使程序運行得更快,它是一個非常廣泛的話題。

軟件產品多種多樣,影響程序執(zhí)行效率的因素很多,因此,性能優(yōu)化,特別是對不熟悉的項目做優(yōu)化,不是一件容易的事。

性能優(yōu)化可分為宏觀和微觀兩個層面。宏觀層面包括架構重構,而微觀層面,則包括算法的優(yōu)化,編譯優(yōu)化,工具分析,高性能編碼等,這些方法是有可能獨立于具體業(yè)務邏輯,因而有更加廣泛的適應性,且更易于實施。

具體到性能優(yōu)化的方法論,首先,應建立度量,你度量什么,你得到什么。所以,性能優(yōu)化測試先行,須基于數(shù)據(jù)而不能憑空猜測,這是做優(yōu)化的一個基本原則。搭建真實的壓測環(huán)境,或者逼近真實環(huán)境,有時候是困難的,也可能非常耗費時間,但它依然是值得的。

有許多工具能幫助我們定位程序瓶頸,有些工具能做很友好的圖形化展示,定位問題是解決問題的前置條件,但定位問題可能不是最難的,分析和優(yōu)化才是最耗時的關鍵環(huán)節(jié),修改之后,要再回歸測試,驗證是否如預期般有效。

什么是高性能程序?架構致廣遠、實現(xiàn)盡精微。

架構優(yōu)化的關鍵是識別瓶頸,這類優(yōu)化有很多套路,比如通過負載均衡做分布式改造,比如用多線程協(xié)程做并行化改造,比如用消息隊列做異步化和解耦,比如用事件通知替代輪詢,比如為數(shù)據(jù)訪問增加緩存,比如用批處理+預取提升吞吐,比如IO與邏輯分離、讀寫分離等等。

架構調整和優(yōu)化雖然收效很大,卻因受限于各種現(xiàn)實因素,因而并不總是可行。

能不做的盡量不做、必須做的高效做是性能優(yōu)化的一個根本法則,提升處理能力和降低計算量可視為性能優(yōu)化的兩個方向。

怎么讓程序跑的更快?這要求我們充分利用硬件的各種特性,想方設法減少等待并且提高并發(fā),提升CACHE命中率,使用更高效的結構和算法;而降低計算量,則可能意味著要跳出純技術范疇,從產品和業(yè)務視角去審視:哪些功能是必須的,哪些功能是可選可配置的。

有時候,我們不得不從細節(jié)的維度去改進程序。通常,我們應該使用簡單的數(shù)據(jù)結構和算法,但如有必要,就應積極使用更高效的結構和算法,不止邏輯結構,物理結構(實現(xiàn))同樣影響執(zhí)行效率;分支預測、反饋優(yōu)化、啟發(fā)性以及基于機器學習編譯優(yōu)化的效果日益凸顯;熟練掌握編程語言深刻理解標準庫實現(xiàn)能幫助我們規(guī)避低性能陷阱;深入細節(jié)做代碼微調甚至指令級優(yōu)化有時候也能取得意想不到的效果。

有時候,我們需要做一些交換,比如用空間置換時間,比如犧牲一些通用性可讀性換取高性能,我們只應當在非常必要的情況下才這么做,它是權衡的藝術。

## 1、架構優(yōu)化

### 負載均衡

負載均衡其實就是解決一個分活的問題,對應到分布式系統(tǒng),一般在邏輯服的前面都會安放一個負載均衡器,比如NGINX就是經典的解決方案。負載均衡不限于分布式系統(tǒng),對于多線程架構的服務器內部,也需要解決負載均衡的問題,讓各個worker線程的負載均衡。

### 多線程、協(xié)程并行化

雖然硬件架構的復雜化對程序開發(fā)提出了更高的要求,但編寫充分利用多CPU多核特性的程序能獲得令人驚嘆的收益,所以,在同樣硬件規(guī)格下,基于多線程/協(xié)程的并行化改造依然值得嘗試。

多線程不可避免要面臨資源競爭的問題,我們的設計目標應該是充分利用硬件多執(zhí)行核心的優(yōu)勢,減少等待,讓多個執(zhí)行流暢快的奔跑起來。

對于多線程模型,如果把每一個要干的活抽象為一個task,把干活的線程抽象為worker,那么,有兩種典型的設計思路,一種是對task類型做出劃分,讓一類或者一個worker去干特定的task,另一種是讓所有worker去干所有task。

第一種劃分,能減少數(shù)據(jù)爭用,編碼實現(xiàn)也更簡單,只需要識別有限的競爭,就能讓系統(tǒng)工作的很好,缺點是任務的工作量很可能不同,有可能導致有些worker忙碌而另一些空閑。

第二種劃分,優(yōu)點是能均衡,缺點是編碼復雜性高,數(shù)據(jù)競爭多。

有時候,我們會綜合上述兩種模式,比如讓單獨的線程去做IO(收發(fā)包)+反序列化(產生protocol task),然后啟動一批worker線程去處理包,中間通過一個task queue去連接,這即是經典的生產者消費者模型。

協(xié)程是一種用戶態(tài)的多執(zhí)行流,它基于一個假設,即用戶態(tài)的任務切換成本低于系統(tǒng)的線程切換。

### 通知替代輪詢

輪詢即不停詢問,就像你每隔幾分鐘去一趟宿管那里查看是否有信件,而通知是你告訴宿管阿姨,你有信的時候,她打電話通知你,顯然輪詢耗費CPU,而通知機制效率更高。

### 添加緩存

緩存的理論依據(jù)是局部性原理。

一般系統(tǒng)的寫入請求遠少于讀請求,針對寫少讀多的場景,很適合引入緩存集群。

在寫數(shù)據(jù)庫的時候同時寫一份數(shù)據(jù)到緩存集群里,然后用緩存集群來承載大部分的讀請求,因為緩存集群很容易做到高性能,所以,這樣的話,通過緩存集群,就可以用更少的機器資源承載更高的并發(fā)。

緩存的命中率一般能做到很高,而且速度很快,處理能力也強(單機很容易做到幾萬并發(fā)),是理想的解決方案。

CDN本質上就是緩存,被用戶大量訪問的靜態(tài)資源緩存在CDN中是目前的通用做法。

### 消息隊列

消息隊列、消息中間件是用來做寫請求異步化,我們把數(shù)據(jù)寫入MessageQueue就認為寫入完成,由MQ去緩慢的寫入DB,它能起到削峰填谷的效果。

消息隊列也是解耦的手段,它主要用來解決寫的壓力。

### IO與邏輯分離、讀寫分離

IO與邏輯分離,這個前面已經講了。讀寫分離是一種數(shù)據(jù)庫應對壓力的慣用措施,當然,它也不僅限于DB。

### 批處理與數(shù)據(jù)預取

批處理是一種思想,分很多種應用,比如多網(wǎng)絡包的批處理,是指把收到的包攢到一起,然后一起過一遍流程,這樣,一個函數(shù)被多次調用,或者一段代碼重復執(zhí)行多遍,這樣i-cache的局部性就很好,另外,如果這個函數(shù)或者一段里要訪問的數(shù)據(jù)被多次訪問,d-cache的局部性也能改善,自然能提升性能,批處理能增加吞吐,但通常會增大延遲。

另一個批處理思想的應用是日志落盤,比如一條日志大概寫幾十個字節(jié),我們可以把它緩存起來,攢夠了一次寫到磁盤,這樣性能會更好,但這也帶來數(shù)據(jù)丟失的風險,不過通常我們可以通過shm的方式規(guī)避這個風險。

指令預取是CPU自動完成的,數(shù)據(jù)預取是一個很有技巧性的工作,數(shù)據(jù)預取的依據(jù)是預取的數(shù)據(jù)將在接下來的操作中用到,它符合空間局部性原理,數(shù)據(jù)預取可以填充流水線,降低訪存等待,但數(shù)據(jù)預取會侵害代碼,且并不總如預期般有效。

哪怕你不增加預取代碼,硬件預取器也有可能幫你做預取,另外gcc也有編譯選項,開啟它會在編譯階段自動插入預取代碼,手動增加預取代碼需要小心處理,時機很重要,最后一定要基于測試數(shù)據(jù),另外,即使表現(xiàn)很好,但代碼修改也有可能導致效果衰減,而且預取語句執(zhí)行本身也有開銷,只有預取的收益大于預取的開銷才是值得的。

累啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦,寫不動啦啦啦!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!哪天有空再寫后面的章節(jié)吧

## 2、算法優(yōu)化

### 哈希(HASH)

#### 哈希和字符串比較

#### HashMap

#### 哈希和平衡搜索樹的比較

### 基于有序數(shù)組的二分查找

### 數(shù)據(jù)結構的實現(xiàn)優(yōu)化

### 延遲計算 & 寫時拷貝

### 預計算

### 增量更新

## 3、代碼優(yōu)化

### 內存優(yōu)化

小對象分配器

內存分配和對象構建分離

### cache優(yōu)化

i-cache優(yōu)化、d-cache優(yōu)化、cache對齊、結構體重排

### 判斷前置

### 整體操作替代小操作

### 復用

### 減法

#### 減少冗余

#### 減少拷貝、零拷貝

#### 減少參數(shù)個數(shù)(寄存器參數(shù)、取決于ABI約定)

#### 減少函數(shù)調用次數(shù)/層次

#### 減少存儲引用次數(shù)

#### 減少無效初始化和重復賦值

### 循環(huán)優(yōu)化

### 防御性編程適可而止

### release干凈

### 慎用遞歸

## 4、編譯優(yōu)化

### inline

### restrict

### LTO

### PGO

### 優(yōu)化選項

## 5、其他優(yōu)化

### 綁核

### SIMD

### 鎖與并發(fā)

#### 鎖的粒度

#### 無鎖編程

#### Per-cpu data structure & thread local

#### 內存屏障

小結

性能優(yōu)化是一項細致的工作,工程師們曾致力于尋找一勞永逸解決性能問題的捷徑,但遺憾的是,沒有銀彈,但這并不意味著性能優(yōu)化無章可循。軟件工程師們在性能優(yōu)化方面積累了大量的經驗,包括架構、緩存、預取、工具、編譯器與編程語言,代碼重構等實踐經驗方方面面,這些方法和探討都具有借鑒意義。

性能優(yōu)化也是一個系統(tǒng)性工程,出現(xiàn)性能瓶頸再優(yōu)化是一種先污染后治理的思路。更好的方式是將性能貫穿于軟件的整個生命周期之中,在設計之初即把性能作為一項需求甚至關鍵目標加以考慮,開發(fā)中持續(xù)監(jiān)控性能的變化并嚴格遵從高性能編碼規(guī)范,后期維護將性能納入維護體系。

嚴格的說,性能優(yōu)化和性能設計有所不同,性能優(yōu)化通常是在現(xiàn)有系統(tǒng)和代碼基礎上做改進,它并非推倒重來,考驗的是開發(fā)者反向修復的能力,而性能設計考驗的是設計者的正向設計能力,但性能優(yōu)化的方法可以指導性能設計,兩者互補。

 

責任編輯:武曉燕 來源: 碼磚雜役
相關推薦

2024-02-29 18:06:39

HTTP性能優(yōu)化

2021-05-19 08:04:11

ASP.Net服務性原則

2024-07-11 08:26:00

2022-03-11 10:23:02

React性能優(yōu)化

2021-11-18 08:20:22

接口索引SQL

2022-03-02 10:36:37

Linux性能優(yōu)化

2022-02-21 13:27:11

接口性能優(yōu)化索引命令

2025-03-13 05:00:00

2021-01-14 08:58:12

Synchronize鎖操作

2023-12-29 08:29:15

QPS系統(tǒng)應用

2024-11-04 09:52:19

單例模式性能內存

2021-06-02 10:00:30

云網(wǎng)絡性能測試

2023-09-01 08:59:57

2021-06-11 06:54:35

DPDK優(yōu)化HugeTLB

2014-12-10 10:12:02

Web

2021-12-02 07:02:16

API性能設計

2020-11-11 10:00:13

NAT性能內核

2009-09-08 09:45:23

App Engine性

2022-02-16 14:10:51

服務器性能優(yōu)化Linux

2021-11-29 11:13:45

服務器網(wǎng)絡性能
點贊
收藏

51CTO技術棧公眾號