Golang泛型是更快了還是慢了? - DoltHub
Go 1.18 已經發布,隨之而來的是對泛型的期待已久的支援!泛型是多年來語言最重大的變化。它們為原本極簡的型別系統增加了一個新維度。
當初一開始,Golang就通過 “介面”支援動態多型;泛型現在為Golang提供靜態多型性。
今天我們將討論 Golang 對泛型的實現以及它對 CPU 和記憶體利用率的意義。
泛型很慢?
在這個重要的版本釋出之後,出現了一波關於Go中泛型變慢的討論,以及它們將如何影響現有的Go專案。
到目前為止,最好的分析是Vincent Marti寫的這個深度分析。如果你還沒有看過,我強烈建議你看一下。
該文章的主要重點是Go編譯器如何實現泛型,以及這些設計決策如何對泛型Go程式碼的效能產生負面影響。
該文章最後總結了Golang泛型的最佳實踐:其中包括 "不要重寫基於介面的API來使用泛型"。
單態化
在大多數常用的語言中,靜態多型性和動態多型性從實現的角度看沒有什麼共同之處。
- 動態多型性最常使用虛擬方法表(簡稱vtables)來實現,在執行時動態解決方法呼叫。
- 靜態多型性通常完全是在編譯時實現的,為每個用於呼叫多型性函式的型別生成一個新版本,這個過程被稱為單態化。
在實現泛型時,Golang團隊選擇了一條中間道路,他們稱之為 "字典和Gcshape Stenciling"。
它是靜態單態化("模版化")和通過vtables("字典")動態呼叫的結合。編譯器不是為每個用於呼叫函式的型別編制一個新的函式,而是按 "gcshape "分組呼叫型別,併為每個gcshape生成一個函式的副本。
一般來說,值型別都有一個獨特的gcshape,但引用型別(指標和介面)都共享一個gcshape:
當你在Golang中把引用型別傳遞給泛型函式時,靜態多型性變成了動態函式排程。
這一設計決定的後果是對效能產生了重大影響。這就是為什麼Vincent Marti的文章得出結論說泛型會使你的程式碼變慢的原因。
它的分析特別關注引用型別,並詳細解釋了當它們與泛型結合使用時,效能如何以及為什麼會下降。
然而,討論中缺少的是泛型與值型別的互動。
泛型是快速的?
我們對泛型的工作原理有了一定的瞭解,而且我們知道它們並沒有為引用型別提供任何明顯的效能優勢。
所以現在的問題是,對於值型別來說,情況是否有任何不同?
我以前寫過關於值型別的效能,以及它們如何比引用型別更好地配合Golang的記憶體模型。長話短說,值型別更容易減少記憶體分配,因為Go編譯器的轉義分析幾乎總是將引用型別放在堆上。
.....更多點選標題
總結
我們已經找到了我們的答案:使用帶有值型資料結構的演算法的通用實現讓我們把資料保留在棧上,避免了記憶體分配的開銷。
我們的引用型別的資料結構會逃到堆中,而不管使用的是什麼函式。這並不是嚴格意義上的必要,因為我們在這裡建立的引用只在堆疊中傳遞,而不是在堆疊中傳遞。
然而,編譯器的轉義分析沒有利用這一事實,而是將其放在堆上。
類似地,我們將我們的值型別資料結構傳遞給函式的介面實現,我們隱含地將它轉換為引用型別,然後它就逃逸到了堆中。
只有當我們把值型別傳遞給它的通用函式的stenciled副本時,編譯器才會避免這種分配。
靜態多型性通常被認為是一種面向效能的特性。就像強型別化一樣,它給編譯器提供了額外的資訊,為生成程式碼時進行更積極的優化提供了機會。這在像C++這樣將泛型函式完全單態化的語言中當然是真的。但就像語言本身一樣,Golang的泛型並不遵循既定的規則,即事情應該是怎樣的。
Golang的泛型函式實際上可以幫助提高效能,但也不是你所期望的那樣。編寫高效能的Go程式碼通常意味著將介面型別限制在高層結構中,這正是我們前面看到的原因:它們與轉義分析不相容,而且幾乎總是導致昂貴的記憶體分配。這使得程式設計師只能使用具體型別,而沒有多型性的設施。泛型可能是這個問題的一個答案。
泛型是Golang的一個全新的特性,對它們的支援只會隨著時間的推移而改善。我們今天的討論完全集中在當前的實現上,但在語言規範中沒有任何東西可以阻止當前設計的改變。
相關文章
- 語言是 Go 還是 Golang?Golang
- Golang 泛型初探Golang泛型
- 長達 12 年,Go 泛型才引入,是政治,還是技術問題?Go泛型
- Golang面試:泛型Golang面試泛型
- 微服務:更愉快還是更嘈雜?微服務
- IT行業更看重學歷還是更看重技術?行業
- 判斷javaScript變數是Ojbect型別還是Array型別JavaScript變數型別
- python 判斷變數是數字型還是字元型Python變數字元
- C#中泛型約束(where)是什麼?C#泛型
- 面試官:說說什麼是泛型的型別擦除?面試泛型型別
- 如果雲更安全 為什麼還是被入侵?
- 男生更看重女生的身材臉蛋,還是思想?
- 在Golang中使用泛型reduce函式 - gosamplesGolang泛型函式
- erp雲化被職業廣泛承受,低價erp上雲是福利還是坑?
- Dice:Android開發者更喜歡Kotlin還是JavaAndroidKotlinJava
- 誰更貴?全球股市,債市,還是房地產?
- golang拾遺:為什麼我們需要泛型Golang泛型
- Golang引入泛型:Go將Interface{}替換為“Any”Golang泛型
- 泛型類、泛型方法及泛型應用泛型
- Golang | 既是介面又是型別,interface是什麼神仙用法?Golang型別
- 【java】【泛型】泛型geneticJava泛型
- 都2020了,還不好好學學泛型?泛型
- SAP Commerce Cloud Storefront 框架選型:Accelerator 還是 Spartacus?Cloud框架
- 泛型類和泛型方法泛型
- 泛型--泛型萬用字元和泛型的上下限泛型字元
- pdf是圖片還是文件 pdf格式是文字檔案還是影像檔案
- 華納雲:Vps伺服器變慢了是什麼原因?伺服器
- Go 泛型之泛型約束Go泛型
- TypeScript 泛型介面和泛型類TypeScript泛型
- 泛型泛型
- RAM是記憶體還是外存記憶體
- PHP Mysql support: 是mysql 還是mysqlnd?PHPMySql
- 資料是黃金還是垃圾?
- 檢視Linux是ubuntu還是centosLinuxUbuntuCentOS
- 更廣泛的重建:經濟轉型的政策途徑
- 還是要理性
- java還是C?Java
- javascript中怎麼判斷某變數是null,undefined,還是不存這個變數 ? 以及變數是array 還是 object 還是 null ?JavaScript變數NullUndefinedObject