亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Go Slice 最大容量大小是怎么來(lái)的

maybe_009 / 1322人閱讀

摘要:會(huì)根據(jù)對(duì)應(yīng)的類型大小去查找表查找索引索引為類型大小,擺放順序是有考慮原因的。

原文地址:Go Slice 最大容量大小是怎么來(lái)的

前言

在《深入理解 Go Slice》中,我們提到了 “根據(jù)其類型大小去獲取能夠申請(qǐng)的最大容量大小” 的處理邏輯。今天我們將更深入地去探究一下,底層到底做了什么東西,涉及什么知識(shí)點(diǎn)?

Go Slice 對(duì)應(yīng)代碼如下:

func makeslice(et *_type, len, cap int) slice {
    maxElements := maxSliceCap(et.size)
    if len < 0 || uintptr(len) > maxElements {
        ...
    }

    if cap < len || uintptr(cap) > maxElements {
        ...
    }

    p := mallocgc(et.size*uintptr(cap), et, true)
    return slice{p, len, cap}
}

根據(jù)想要追尋的邏輯,定位到了 maxSliceCap 方法,它會(huì)根據(jù)當(dāng)前類型的大小獲取到了所允許的最大容量大小來(lái)進(jìn)行閾值判斷,也就是安全檢查。這是淺層的了解,我們繼續(xù)追下去看看還做了些什么?

maxSliceCap
func maxSliceCap(elemsize uintptr) uintptr {
    if elemsize < uintptr(len(maxElems)) {
        return maxElems[elemsize]
    }
    return maxAlloc / elemsize
}
maxElems
var maxElems = [...]uintptr{
    ^uintptr(0),
    maxAlloc / 1, maxAlloc / 2, maxAlloc / 3, maxAlloc / 4,
    maxAlloc / 5, maxAlloc / 6, maxAlloc / 7, maxAlloc / 8,
    maxAlloc / 9, maxAlloc / 10, maxAlloc / 11, maxAlloc / 12,
    maxAlloc / 13, maxAlloc / 14, maxAlloc / 15, maxAlloc / 16,
    maxAlloc / 17, maxAlloc / 18, maxAlloc / 19, maxAlloc / 20,
    maxAlloc / 21, maxAlloc / 22, maxAlloc / 23, maxAlloc / 24,
    maxAlloc / 25, maxAlloc / 26, maxAlloc / 27, maxAlloc / 28,
    maxAlloc / 29, maxAlloc / 30, maxAlloc / 31, maxAlloc / 32,
}

maxElems 是包含一些預(yù)定義的切片最大容量值的查找表,索引是切片元素的類型大小。而值看起來(lái) “奇奇怪怪” 不大眼熟,都是些什么呢。主要是以下三個(gè)核心點(diǎn):

^uintptr(0)

maxAlloc

maxAlloc / typeSize

^uintptr(0)
func main() {
    log.Printf("uintptr: %v
", uintptr(0))
    log.Printf("^uintptr: %v
", ^uintptr(0))
}

輸出結(jié)果:

2019/01/05 17:51:52 uintptr: 0
2019/01/05 17:51:52 ^uintptr: 18446744073709551615

我們留意一下輸出結(jié)果,比較神奇。取反之后為什么是 18446744073709551615 呢?

uintptr 是什么

在分析之前,我們要知道 uintptr 的本質(zhì)(真面目),也就是它的類型是什么,如下:

type uintptr uintptr

uintptr 的類型是自定義類型,接著找它的真面目,如下:

#ifdef _64BIT
typedef    uint64        uintptr;
#else
typedef    uint32        uintptr;
#endif

通過(guò)對(duì)以上代碼的分析,可得出以下結(jié)論:

在 32 位系統(tǒng)下,uintptr 為 uint32 類型,占用大小為 4 個(gè)字節(jié)

在 64 位系統(tǒng)下,uintptr 為 uint64 類型,占用大小為 8 個(gè)字節(jié)

^uintptr 做了什么事

^ 位運(yùn)算符的作用是按位異或,如下:

func main() {
    log.Println(^1)
    log.Println(^uint64(0))
}

輸出結(jié)果:

2019/01/05 20:44:49 -2
2019/01/05 20:44:49 18446744073709551615

接下來(lái)我們分析一下,這兩段代碼都做了什么事情呢

^1

二進(jìn)制:0001

按位取反:1110

該數(shù)為有符號(hào)整數(shù),最高位為符號(hào)位。低三位為表示數(shù)值。按位取反后為 1110,根據(jù)先前的說(shuō)明,最高位為 1,因此表示為 -。取反后 110 對(duì)應(yīng)十進(jìn)制 -2

^uint64(0)

二進(jìn)制:0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

按位取反:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111

該數(shù)為無(wú)符號(hào)整數(shù),該位取反后得到十進(jìn)制值為:18446744073709551615

這個(gè)值是不是看起來(lái)很眼熟呢?沒(méi)錯(cuò),就是 ^uintptr(0) 的值。也印證了其底層數(shù)據(jù)類型為 uint64 的事實(shí) (本機(jī)為 64 位)。同時(shí)它又代表如下:

math.MaxUint64

2 的 64 次方減 1

maxAlloc
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchWasm = 0

...

_64bit = 1 << (^uintptr(0) >> 63) / 2

heapAddrBits = (_64bit*(1-sys.GoarchWasm))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle))

maxAlloc = (1 << heapAddrBits) - (1-_64bit)*1

maxAlloc允許用戶分配的最大虛擬內(nèi)存空間。在 64 位,理論上可分配最大 1 << heapAddrBits 字節(jié)。在 32 位,最大可分配小于 1 << 32 字節(jié)

在本文,僅需了解它承載的是什么就好了。具體的在以后內(nèi)存管理的文章再講述

注:該變量在 go 10.1 為 _MaxMem,go 11.4 已改為 maxAlloc。相關(guān)的 heapAddrBits 計(jì)算方式也有所改變

maxAlloc / typeSize

我們?cè)俅位仡?maxSliceCap 的邏輯代碼,這次重點(diǎn)放在控制邏輯,如下:

// func makeslice
maxElements := maxSliceCap(et.size)

...

// func maxSliceCap
if elemsize < uintptr(len(maxElems)) {
    return maxElems[elemsize]
}
return maxAlloc / elemsize

通過(guò)這段代碼和 Slice 上下文邏輯,可得知在想得到該類型的最大容量大小時(shí)。會(huì)根據(jù)對(duì)應(yīng)的類型大小去查找表查找索引(索引為類型大小,擺放順序是有考慮原因的)?!捌炔坏靡训那闆r下” 才會(huì)手動(dòng)的計(jì)算它的值,最終計(jì)算得到的內(nèi)存字節(jié)大小都為該類型大小的整數(shù)倍

查找表的設(shè)置,更像是一個(gè)優(yōu)化邏輯。減少常用的計(jì)算開(kāi)銷 :)

總結(jié)

通過(guò)本文的分析,可得出 Slice 所允許申請(qǐng)的最大容量大小,與當(dāng)前值類型和當(dāng)前平臺(tái)位數(shù)有直接關(guān)系

最后

本文與《有點(diǎn)不安全卻又一亮的 Go unsafe.Pointer》一同屬于《深入理解 Go Slice》的關(guān)聯(lián)章節(jié)。如果你在閱讀源碼時(shí),對(duì)這些片段有疑惑。記得想盡辦法深究下去,搞懂它

短短的一句話其實(shí)蘊(yùn)含著不少知識(shí)點(diǎn),希望這篇文章恰恰好可以幫你解惑

注:本文 Go 代碼基于版本 11.4

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/29895.html

相關(guān)文章

  • golang學(xué)習(xí)筆記(一)——golang基礎(chǔ)和相關(guān)數(shù)據(jù)結(jié)構(gòu)

    摘要:小白前端一枚,最近在研究,記錄自己學(xué)習(xí)過(guò)程中的一些筆記,以及自己的理解。此外,結(jié)構(gòu)體也支持嵌套。在函數(shù)聲明時(shí),在函數(shù)名前放上一個(gè)變量,這個(gè)變量稱為方法的接收器,一般是結(jié)構(gòu)體類型的。 小白前端一枚,最近在研究golang,記錄自己學(xué)習(xí)過(guò)程中的一些筆記,以及自己的理解。 go中包的依賴管理 go中的切片 byte 和 string go中的Map go中的struct結(jié)構(gòu)體 go中的方...

    lyning 評(píng)論0 收藏0
  • PHP轉(zhuǎn)Go系列:數(shù)組與切片

    摘要:以上是數(shù)組在語(yǔ)言中的定義方法,代表數(shù)組長(zhǎng)度為,是數(shù)組中元素的類型,花括號(hào)中的是數(shù)組元素,切記元素個(gè)數(shù)與類型一定要與前面聲明的相符,否則會(huì)報(bào)錯(cuò)。數(shù)組元素的刪除在中刪除數(shù)組元素非常簡(jiǎn)單,直接即可,以下代碼是刪除第二個(gè)元素。 數(shù)組的定義 用過(guò)PHP的同學(xué)應(yīng)該很清楚,無(wú)論多么復(fù)雜的數(shù)據(jù)格式都可以用數(shù)組來(lái)表達(dá),什么類型的數(shù)據(jù)都可以往里塞,它是工作必備的一部分,使用很簡(jiǎn)單,易用程度簡(jiǎn)直變態(tài)。 $a...

    yuxue 評(píng)論0 收藏0
  • 深入理解 Go map:賦值和擴(kuò)容遷移

    摘要:我相信這樣你能更好的讀懂這篇文章原文地址深入理解賦值和擴(kuò)容遷移哈希函數(shù)哈希函數(shù),又稱散列算法散列函數(shù)。而一個(gè)好的哈希函數(shù),應(yīng)當(dāng)盡量少的出現(xiàn)哈希沖突,以此保證操作哈希表的時(shí)間復(fù)雜度但是哈希沖突在目前來(lái)講,是無(wú)法避免的。 概要 在 上一章節(jié) 中,數(shù)據(jù)結(jié)構(gòu)小節(jié)里講解了大量基礎(chǔ)字段,可能你會(huì)疑惑需要 #&(!……#(!¥! 來(lái)干嘛?接下來(lái)我們一起簡(jiǎn)單了解一下基礎(chǔ)概念。再開(kāi)始研討今天文章的重點(diǎn)內(nèi)...

    wudengzan 評(píng)論0 收藏0
  • go實(shí)現(xiàn)LRU cache

    摘要:簡(jiǎn)介概述緩存資源通常比較昂貴通常數(shù)據(jù)量較大時(shí)會(huì)竟可能從較少的緩存滿足盡可能多訪問(wèn)這里有一種假設(shè)通常最近被訪問(wèn)的數(shù)據(jù)那么它就有可能會(huì)被后續(xù)繼續(xù)訪問(wèn)基于這種假設(shè)將所有的數(shù)據(jù)按訪問(wèn)時(shí)間進(jìn)行排序并按驅(qū)逐出舊數(shù)據(jù)那么存在緩存的數(shù)據(jù)就為熱點(diǎn)數(shù)據(jù)這樣既節(jié) 1. LRU簡(jiǎn)介 1.1 概述 緩存資源通常比較昂貴,通常數(shù)據(jù)量較大時(shí),會(huì)竟可能從較少的緩存滿足盡可能多訪問(wèn),這里有一種假設(shè),通常最近被訪問(wèn)的數(shù)據(jù)...

    Jackwoo 評(píng)論0 收藏0
  • Netty ByteBuf

    摘要:主要用來(lái)檢測(cè)對(duì)象是否泄漏。子類實(shí)現(xiàn)相關(guān)的方法是否支持?jǐn)?shù)組,判斷緩沖區(qū)的實(shí)現(xiàn)是否基于字節(jié)數(shù)組如果緩沖區(qū)的實(shí)現(xiàn)基于字節(jié)數(shù)組,返回字節(jié)數(shù)組 ByteBuf ByteBuf需要提供JDK ByteBuffer的功能(包含且不限于),主要有以下幾類基本功能: 7種Java基礎(chǔ)類型、byte[]、ByteBuffer(ByteBuf)的等的讀寫(xiě) 緩沖區(qū)自身的copy和slice 設(shè)置網(wǎng)絡(luò)字節(jié)序 ...

    meislzhua 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<