高性能Go並發


1.管道chan吞吐極限10,000,000,單次Put,Get耗時大約100ns/op,無論是采用單Go程,還是多Go程並發(並發數:100, 10000, 100000),耗時均沒有變化,Go內核這對chan進行優化。

解決之道:在系統設計時,避免使用管道chan傳遞主業務數據,避免將業務流程處理流程分割到對個Go程中執行,這樣做減少chan傳輸耗時,和Go程調度耗時,性能會有很大的提升。

案例分析:nsq和nats都是實時消息隊列,nsq在客戶端端和服務端大量使用chan轉發消息,導致性能不佳,只有100,000/s;而nats服務端在分發消息流程中,沒有使用chan,只在客戶端接收時使用chan,性能可達到1,000,000/s。

2.互斥鎖Mutex在單Go程時Lock,Unlock耗時大約20ns/op,但是采用多Go程時,性能急劇下降,並發越大耗時越長,在Go1.5並發數達到1024耗時900ns/op,Go1.6優化到300ns/op,究其原因,是構建在CPU的原子操作之上,搶占過於頻繁將導致,消耗大量CPU時鍾,進而CPU多核無法並行。

解決之道:采用分區,將需要互斥保護的數據,分成多個固定分區(建議是2的整數倍,如256),訪問時先定位分區(不互斥),這樣就可降低多個Go程競爭1個數據分區的概率。

案例分析:Golang的Go程調度模塊,在管理大量的Go程,使用的就是數據分區。

3.select異步操作在單管道時耗時120ns/op,但是隨着管道數增加,性能線性下降,每增加1個管道增加100ns/op,究其原因,slelect時當chan數超過1后,Go內部是創建一個Go程,有它每1ms輪訓的方式檢查每個chan是否可用,而不是采用事件觸發。

解決之道:在select中避免使用過多的管道chan分支,或者把無法用到的chan置為nil;解決select超時,避免使用單獨的超時管道,應與數據返回管道共享。

案例分析:nsq和nats都是實時消息隊列,由於nsq大量使用chan,這就必然導致大量使用select對多chan操作,結果是性能不高。

4.Go調度性能低下,當出現1,000,000Go程時,Go的調度器的性能急劇下降。

解決之道:避免動態創建Go程,服務端收到數據並處理的流程中,避免使用chan傳遞業務數據,這樣會引起Go程調度。

案例分析:nsq和nats都是實時消息隊列,由於nsq大量使用chan,這就必然導致在服務過程中,引起Go調度,結果是性能不高。

5.defer性能不高,每次defer耗時100ns,,在一個func內連續出現多次,性能消耗是100ns*n,累計出來浪費的cpu資源很大的。

解決之道:除了需要異常捕獲時,必須使用defer;其它資源回收類defer,可以判斷失敗后,使用goto跳轉到資源回收的代碼區。

補充:defer 在 go1.8 快了一倍了。runtime: defer is slow · Issue #14939 · golang/go · GitHub

6.內存管理器性能低下,申請16字節的內存,單次消耗30ns,64字節單次消耗70ns,隨着申請內存尺寸的增長,耗時會迅速增長。加上GC的性能在1.4, 1.5是都不高,直到1.6, 1.7才得到改善。

解決之道:建議使用pool,單次Put,Get的耗時大約在28ns,在並發情況下可達到18ns,比起每次創建,會節省很多的CPU時鍾。

補充: 單純看 Put, Get 耗時不高,但是 pool 取出來的是 interface{},需要類型斷言成實際類型,放進去的時候,還要把實際類型轉換成 interface{}(雖然是自動的),這個轉換的過程對於簡單類型每次需要 30ns,復雜的結構體時間會長的多,所以這個開銷算上的話,用 pool 方案反而會導致性能下降。

 

 

出於性能考慮的最佳實踐和建議

 

(1)盡可能的使用:=去初始化聲明一個變量(在函數內部);

 

(2)盡可能的使用字符代替字符串;

 

(3)盡可能的使用切片代替數組;

 

(4)盡可能的使用數組和切片代替映射(詳見參考文獻15);

 

(5)如果只想獲取切片中某項值,不需要值的索引,盡可能的使用for range去遍歷切片,這比必須查詢切片中的每個元素要快一些;

 

(6)當數組元素是稀疏的(例如有很多0值或者空值nil),使用映射會降低內存消耗;

 

(7)初始化映射時指定其容量;

 

(8)當定義一個方法時,使用指針類型作為方法的接受者;

 

(9)在代碼中使用常量或者標志提取常量的值;

 

(10)盡可能在需要分配大量內存時使用緩存;

 

(11)使用緩存模板(參考章節15.7)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM