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時鐘。