Golang號稱高併發,但高併發時效能不高

2021-08-21 09:03:09 字數 1480 閱讀 1707

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跳轉到資源**的**區。

6.記憶體管理器效能低下,申請16位元組的記憶體,單次消耗30ns,64位元組單次消耗70ns,隨著申請記憶體尺寸的增長,耗時會迅速增長。加上gc的效能在1.4, 1.5是都不高,直到1.6, 1.7才得到改善。

解決之道:建議使用pool,單次put,get的耗時大約在28ns,在併發情況下可達到18ns,比起每次建立,會節省很多的cpu時鐘。

高併發 高可用

高併發 提高系統併發能力的方法主要有兩種 前者垂直擴充套件可以通過提公升單機硬體效能,或者提公升單機架構效能,來提高併發性,但單機效能總是有極限的,網際網路分布式架構設計高併發終極解決方案還是後者 水平擴充套件。網際網路分層架構中,各層次水平擴充套件的實踐又有所不同 1 反向 層可以通過 dns輪詢...

高併發 高併發測試筆記

問 高併發測試 一般你們用什麼工具來模擬 10萬級別的客戶端併發?在普通的電腦上可以模擬嗎 10萬併發需要至少10萬的套接字,套接字在核心中占用記憶體100000 6k 2 1g記憶體,系統需要能夠開啟10w個fd。一般的系統能夠能模擬 問 預設每個程序只能開1024個fd,修改後最大可以10w,那...

Golang百萬級高併發實踐

go語言作為新興的語言,最近發展勢頭很是迅猛,其最大的特點就是原生支援併發。它使用的是 協程 goroutine 模型 和傳統基於 os 執行緒和程序實現不同,go 語言的併發是基於使用者態的併發,這種併發方式就變得非常輕量,能夠輕鬆執行幾萬併發邏輯。go 的併發屬於 csp 併發模型的一種實現,c...