欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang中map縮容的實(shí)現(xiàn)

 更新時(shí)間:2025年03月04日 11:24:00   作者:李若盛開  
本文主要介紹了Go語(yǔ)言中map的擴(kuò)縮容機(jī)制,包括grow和hashGrow方法的處理,具有一定的參考價(jià)值,感興趣的可以了解一下

基本分析

在 Go 底層源碼 src/runtime/map.go 中,擴(kuò)縮容的處理方法是 grow 為前綴的方法來(lái)處理的。

其中擴(kuò)縮容涉及到的是插入元素的操作,對(duì)應(yīng) mapassign 方法:

func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
  ...
 if !h.growing() && (overLoadFactor(h.count+1, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
  hashGrow(t, h)
  goto again
 }
  ...
}
func (h *hmap) growing() bool {
 return h.oldbuckets != nil
}
func overLoadFactor(count int, B uint8) bool {
 return count > bucketCnt && uintptr(count) > loadFactorNum*(bucketShift(B)/loadFactorDen)
}
func tooManyOverflowBuckets(noverflow uint16, B uint8) bool {
 if B > 15 {
  B = 15
 }
 return noverflow >= uint16(1)<<(B&15)
} 

核心看到針對(duì)擴(kuò)縮容的判斷邏輯:

當(dāng)前沒有在擴(kuò)容:條件為 oldbuckets 不為 nil。

是否可以進(jìn)行擴(kuò)容:條件為 hmap.count> hash 桶數(shù)量 (2^B)*6.5。其中 hmap.count 指的是map 的數(shù)據(jù)數(shù)目, 2^B 僅指 hash 數(shù)組的大小,不包含溢出桶。

是否可以進(jìn)行縮容:條件為溢出桶(noverflow)的數(shù)量 >= 32768(1<<15)。

可以關(guān)注到,無(wú)論是擴(kuò)容還是縮容,其都是由 hashGrow 方法進(jìn)行處理:

 func hashGrow(t *maptype, h *hmap) {
 bigger := uint8(1)
 if !overLoadFactor(h.count+1, h.B) {
  bigger = 0
  h.flags |= sameSizeGrow
 }
  ...
}

若是擴(kuò)容,則 bigger 為 1,也就是 B+1。代表 hash 表容量擴(kuò)大 1 倍。不滿足就是縮容,也就是 hash 表容量不變。

可以得出結(jié)論:map 的擴(kuò)縮容的主要區(qū)別在于 hmap.B 的容量大小改變。而縮容由于 hmap.B 壓根沒變,內(nèi)存空間的占用也是沒有變化的。

帶來(lái)的隱患

這種方式其實(shí)是存在運(yùn)行隱患的,也就是導(dǎo)致在刪除元素時(shí),并不會(huì)釋放內(nèi)存,使得分配的總內(nèi)存不斷增加。如果一個(gè)不小心,拿 map 來(lái)做大 key/value 的存儲(chǔ),也不注意管理,很容易就內(nèi)存爆了。

也就是 Go 語(yǔ)言的 map 目前實(shí)現(xiàn)的是 “偽縮容”,僅針對(duì)溢出桶過(guò)多的情況。若是觸發(fā)縮容,hash 數(shù)組的占用的內(nèi)存大小不變(等量擴(kuò)容)。

若要實(shí)現(xiàn) ”真縮容“,Go Contributor @josharian 表示目前唯一可用的解決方法是:創(chuàng)建一個(gè)新的 map 并從舊的 map 中復(fù)制元素。

示例如下:

old := make(map[int]int, 9999999)
new := make(map[int]int, len(old))
for k, v := range old {
    new[k] = v
}
old = new
...

為什么不支持縮容

下述內(nèi)容會(huì)主要基于如下兩個(gè) issues 和 proposal 來(lái)分析:

《runtime: shrink map as elements are deleted[1]》
《proposal: runtime: add way to clear and reuse a map's working storage[2]》

目前 map 的縮容處理起來(lái)比較棘手,最早的 issues 是 2016 年提出的,也有人提過(guò)一些提案,但都因?yàn)榉N種原因被拒絕了。

簡(jiǎn)單來(lái)講,就是沒有找到一個(gè)很好的方法實(shí)現(xiàn),存在明確的實(shí)現(xiàn)成本問(wèn)題,沒辦法很方便的 ”告訴“ Go 運(yùn)行時(shí),我要:

  • 記得保留存儲(chǔ)空間,我要立即重用 map。
  • 趕緊釋放存儲(chǔ)空間,map 從現(xiàn)在開始會(huì)小很多。

抽象來(lái)看癥結(jié)是:需要保證增長(zhǎng)結(jié)果在下一個(gè)開始之前完成,此處的增長(zhǎng)指的是 ”從小到大,從一個(gè)大小到相同大小,從大到小“ 的復(fù)雜過(guò)程。

這屬于一個(gè)多重 case,從而導(dǎo)致也就一直拖著,慢慢想。

到此這篇關(guān)于Golang中map縮容的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Golang map縮容 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang詳細(xì)講解常用Http庫(kù)及Gin框架的應(yīng)用

    Golang詳細(xì)講解常用Http庫(kù)及Gin框架的應(yīng)用

    下面這篇文章主要給大家介紹了關(guān)于Golang常用的Http庫(kù)及Gin框架,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 解析Golang中的鎖競(jìng)爭(zhēng)問(wèn)題

    解析Golang中的鎖競(jìng)爭(zhēng)問(wèn)題

    這篇文章主要介紹了golang中的鎖競(jìng)爭(zhēng)問(wèn)題,本文通過(guò)實(shí)例代碼給大家詳細(xì)講解,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • go語(yǔ)言使用range來(lái)接收通道里面的數(shù)據(jù)

    go語(yǔ)言使用range來(lái)接收通道里面的數(shù)據(jù)

    本文主要介紹了go語(yǔ)言使用range來(lái)接收通道里面的數(shù)據(jù),for ... range?循環(huán)會(huì)一直從通道中接收值,直到通道關(guān)閉并且所有值都被接收完畢,下面就來(lái)介紹一下,感興趣的可以了解一下
    2025-04-04
  • Golang設(shè)計(jì)模式之生成器模式講解和代碼示例

    Golang設(shè)計(jì)模式之生成器模式講解和代碼示例

    生成器是一種創(chuàng)建型設(shè)計(jì)模式,使你能夠分步驟創(chuàng)建復(fù)雜對(duì)象,與其他創(chuàng)建型模式不同,生成器不要求產(chǎn)品擁有通用接口,這使得用相同的創(chuàng)建過(guò)程生成不同的產(chǎn)品成為可能,本文就通過(guò)代碼示例為大家詳細(xì)介紹Golang生成器模式,感興趣的同學(xué)可以參考下
    2023-06-06
  • Go語(yǔ)言Cookie用法分析

    Go語(yǔ)言Cookie用法分析

    這篇文章主要介紹了Go語(yǔ)言Cookie用法,結(jié)合實(shí)例形式分析了Go語(yǔ)言Cookie的設(shè)置、讀取等相關(guān)操作技巧,需要的朋友可以參考下
    2017-02-02
  • Go語(yǔ)言操作數(shù)據(jù)庫(kù)及其常規(guī)操作的示例代碼

    Go語(yǔ)言操作數(shù)據(jù)庫(kù)及其常規(guī)操作的示例代碼

    這篇文章主要介紹了Go語(yǔ)言操作數(shù)據(jù)庫(kù)及其常規(guī)操作的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Go語(yǔ)言實(shí)現(xiàn)RSA加解密算法詳解

    Go語(yǔ)言實(shí)現(xiàn)RSA加解密算法詳解

    隨著互聯(lián)網(wǎng)的高速發(fā)展,人們對(duì)安全的要求也越來(lái)越高,加解密也變得越來(lái)越重要,本文主要為大家介紹了Go語(yǔ)言中實(shí)現(xiàn)RSA加解密與簽名驗(yàn)證算法,希望對(duì)大家有所幫助
    2023-06-06
  • Beego中ORM操作各類數(shù)據(jù)庫(kù)連接方式詳細(xì)示例

    Beego中ORM操作各類數(shù)據(jù)庫(kù)連接方式詳細(xì)示例

    這篇文章主要為大家介紹了Beego中ORM操作各類數(shù)據(jù)庫(kù)連接方式詳細(xì)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Go使用協(xié)程交替打印字符

    Go使用協(xié)程交替打印字符

    這篇文章主要介紹了Go使用協(xié)程交替打印字符,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • Golang實(shí)現(xiàn)反向代理的示例代碼

    Golang實(shí)現(xiàn)反向代理的示例代碼

    這篇文章主要為大家學(xué)習(xí)介紹了如何利用Golang實(shí)現(xiàn)反向代理,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-07-07

最新評(píng)論