Go語言本來就以輕量快速著稱,一位GitHub員工卻偶然發現:
只改變一個字符的位置,能把一段代碼運行速度提高足足42%。

簡直就像是……

這個簡單有效的技巧一經發布,就引來眾多程序員圍觀。
原作者自己也調侃,一般這種情況都是事先犯了個愚蠢的錯誤,后面才能提升這么大。
不過順著這個思路發現有人發現,就連Go開發團隊的核心人物Russ Cox都在標準庫中犯過同樣的錯誤。

什么樣的錯誤?
發現這個問題的Harry在大型程序員交友平臺GitHub工作。
他在開發一個把GitHub倉庫中每個文件的所有者列出來的小工具。
功能很簡單,就是根據CODEOWNERS文件中定義的規則匹配,寫在越下面的規則優先級越高。

原理也很簡單,就是從后往前一條一條處理,匹配到了就停止。

但就是這樣一個簡單的程序卻出現了性能問題,處理中等大小的倉庫就很慢了。

他打印出火焰圖,發現大部分時間都花在了Go語言的正則表達式引擎中。
另外在內存動態分配malloc和垃圾回收gc上面的花費也值得注意。

要減少malloc的時間,就需要用到Go語言的逃逸分析(Escape Analysis)了。
簡單來說,就是盡量把變量分配到棧上,讓編譯器自動管理內存的釋放。
只有在“逃逸”也就是變量的作用域超出所在的棧時,才把變量分配到堆上,減輕運行時GC的壓力。
在這次的程序中,Harry確定了逃逸的變量是rule這個結構體(struct)。

但問題是,rule存儲在RuleSet這個切片(slice)里,按Go語言的規則可以確信他已經在堆中了。
再分析一下代碼,發現在給rule賦值的時候實際上是做了一次不必要的拷貝,后面用“&”取地址時候創建了一個逃逸的指針指向它的副本。

最后解決辦法也很容易想出,只需要把&移動到上面。

這樣就引用了切片中的結構體,避免了拷貝。
如何徹底避免?
在熱議中,有網友分享了自己是怎么避免出現這個問題的。
對于每個結構體,把它看作純值或純指針,壓根就不去使用&這種取地址的操作,避免隱式的內存分配。

如果你想要深入理解這個問題,也有人貼心的給出了需要提前了解的一些背景知識。

最后有人指出,Rust語言為避免這個問題,直接規定必須顯式操作才能拷貝一個數據結構。

當你不習慣的時候這規定煩得要命,但是總的來看還是值得。
方便or規范,你更傾向于哪種做法?
審核編輯 :李倩
-
代碼
+關注
關注
30文章
4968瀏覽量
73967 -
go語言
+關注
關注
1文章
159瀏覽量
9779
原文標題:只改變一個字符使 Go 程序提速 42%
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
求助 LabVIEW 字符串比較
keil定義fputc函數
單片機中的串口通訊串行同步通信與串行異步通信
串口超時中斷的原理與特點
飛凌嵌入式ElfBoard-標準IO接口之格式化輸入
原廠 FZH173是點陣式液晶顯示驅動電路 LCD驅動
RISC-V的工具鏈GCC內聯匯編
E203串口中斷使用總結
電子加工企業必看!AI 視覺檢測讓馬達保護器良率飆升,成本驟降!
rt thread 按照官方視頻一個字一個字敲都不行,連main函數都無法進入,為什么?
求助,關于STM32F030的iic主收問題求解
常用通信接口一(串口、RS232、RS485、USB、TYPE-C原理與區別)
只改變一個字符使Go程序提速42%
評論