Dig101-Go 之 interface 呼叫的一個優化點
檢視更多:歷史集錄
Dig101: dig more, simplified more and know more
今天談下上文 ( Dig101-Go 之讀懂 interface 的底層設計 ) 留下的那個問題:
為什麼對於以下 interface Stringer
和構造型別 Binary
下面程式碼conversion
會呼叫轉換函式convT64
,而devirt
不會呼叫?
func conversion() {
var b Stringer
var i Binary = 1
b = i //convT64
_=b.String()
}
func devirt() {
var b Stringer = Binary(1)
_ = b.String() //static call Binary.String
}
這裡可以使用 ssa 視覺化工具檢視,更容易瞭解每行程式碼的編譯過程 如
GOSSAFUNC=main go1.14 build types/interface/interface.go
生成ssa.html
事有蹊蹺,必是優化!
搜尋發現相關 issue Devirtualize calls when concrete type behind interface is statically known 和提交 De-virtualize interface calls
原來這個是為了優化如果 interface 內部的構造型別如果可以內聯後被靜態推斷出來的話,就將其直接重寫為靜態呼叫
最初主要希望避免一些 interface 呼叫的 gc 壓力(interface 呼叫在逃逸分析時,會使函式的接受者 (receiver
) 和引數 (argument
) 逃逸到堆上(而不是留在棧上),增加 gc 壓力。不過這一點目前還未實現,參見Use devirtualization in escape analysis)
暫時先優化為靜態呼叫避免轉換呼叫(convXXX
),減少程式碼大小和提升細微的效能
摘錄主要處理點如下:
// 對iface=類指標(pointer-shaped)構造型別 記錄itab
// 用於後續優化掉 OCONVIFACE
cmd/compile/internal/gc/subr.go:implements
if isdirectiface(t0) && !iface.IsEmptyInterface() {
itabname(t0, iface)
}
cmd/compile/internal/gc/reflect.go:itabname
itabs = append(itabs, itabEntry{t: t, itype: itype, lsym: s.Linksym()})
// 編譯前,獲取itabs
cmd/compile/internal/gc/reflect.go:peekitabs
// ssa時利用函式內聯和itabs推斷可重寫為靜態呼叫,避免convXXX
cmd/compile/internal/ssa/rewrite.go:devirt
Go 編譯步驟相關參見 Go compiler
這種優化對於常見的返回 interface 的建構函式還是有幫助的。
func New() Interface { return &impl{...} }
要注意返回構造型別需為類指標才可以。
我們可以利用這一點來應用此 interface 呼叫優化
想了解更多,可以檢視Devirtualize 的測試程式碼
本文程式碼見 NewbMiao/Dig101-Go
文章首發公眾號:newbmiao
推薦閱讀:Dig101-Go 系列
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 站點優化之 WebP 實戰優化Web
- Spring Cloud之微服務之間相互呼叫、如何讓一個微服務呼叫另外一個微服務SpringCloud微服務
- 發現一個開源專案優化點,點進來就是你的了優化
- Golang之interfaceGolang
- 【MySQL】NOT EXISTS優化的一個案例MySql優化
- 遞迴尾呼叫優化遞迴優化
- 圖解尾呼叫優化圖解優化
- 搭建 VuePress 站點必做的 10 個優化Vue優化
- 對於iOS效能優化的一點看法iOS優化
- 函式呼叫的代價與優化函式優化
- 一勞永逸的優化!併發RPC呼叫小工具優化RPC
- 如何判斷一個 interface{} 的值是否為 nil ?
- netty系列之:一個價值上億的網站速度優化方案Netty網站優化
- oracle之優化一用group by或exists優化distinctOracle優化
- 前端效能優化的點前端優化
- IPv6優點之層次化的地址結構
- MySQL之SQL優化詳解(一)MySql優化
- [效能優化]UITableView效能優化的一點感悟及計算UILabel高度的新方法優化UIView
- 尾呼叫、優化和 ES6優化
- 遞迴優化:尾呼叫和Memoization遞迴優化
- 資料視覺化的優點是什麼(一)視覺化
- 前端效能優化實踐 之 百度App個人主頁優化前端優化APP
- dubbo泛化呼叫導致zk中同一個消費者節點數遞增
- sql優化之邏輯優化SQL優化
- 記一個效能優化問題優化
- Android優化——繪製優化之android系統顯示原理(一)Android優化
- Android效能優化之佈局優化Android優化
- NoSQL之Redis的配置優化SQLRedis優化
- 關於《明日方舟》單局優點的一個思考
- 兩個JS之間的函式互相呼叫JS函式
- 分享一個SQLite 效能優化例項SQLite優化
- MySQL調優之索引優化MySql索引優化
- 運籌優化(五)--線性規劃之內點法優化
- Android 效能優化之記憶體優化Android優化記憶體
- Android效能優化篇之服務優化Android優化
- MySQL優化之系統變數優化MySql優化變數
- 難住了,微服務之間的呼叫方式哪種更優?微服務
- js 呼叫棧機制與ES6尾呼叫優化介紹JS優化