真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

go語言uintptr go語言適合做什么

Go 數(shù)據(jù)類型(三)整型及運算符

int8 , uint8

創(chuàng)新互聯(lián)公司長期為近千家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為向陽企業(yè)提供專業(yè)的成都網(wǎng)站設計、做網(wǎng)站,向陽網(wǎng)站改版等技術(shù)服務。擁有十余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

int16 , uint16

int32 , uint32

int64 , uint64

int , uint , uintptr

Go為強類型語言,所以上述類型默認為不同類型

如需運算,可通過強制類型轉(zhuǎn)換

+ , - , * , / , %

, , == , = , = 和 !=

比較運算符計算的結(jié)果是布爾值

位與: xy

位或: x|y

異或: x^y

取反: ^x

左移:

右移:

邏輯運算符的計算結(jié)果也是布爾值

邏輯與: xy

邏輯或: x||y

邏輯非: !x

Go語言使用 map 時盡量不要在 big map 中保存指針

不知道你有沒有聽過這么一句:在使用 map 時盡量不要在 big map 中保存指針。好吧,你現(xiàn)在已經(jīng)聽過了:)為什么呢?原因在于 Go 語言的垃圾回收器會掃描標記 map 中的所有元素,GC 開銷相當大,直接GG。

這兩天在《Mastering Go》中看到 GC 這一章節(jié)里面對比 map 和 slice 在垃圾回收中的效率對比,書中只給出結(jié)論沒有說明理由,這我是不能忍的,于是有了這篇學習筆記。扯那么多,Show Your Code

這是一個簡單的測試程序,保存字符串的 map 和 保存整形的 map GC 的效率相差幾十倍,是不是有同學會說明明保存的是 string 哪有指針?這個要說到 Go 語言中 string 的底層實現(xiàn)了,源碼在 src/runtime/string.go里,可以看到 string 其實包含一個指向數(shù)據(jù)的指針和一個長度字段。注意這里的是否包含指針,包括底層的實現(xiàn)。

Go 語言的 GC 會遞歸遍歷并標記所有可觸達的對象,標記完成之后將所有沒有引用的對象進行清理。掃描到指針就會往下接著尋找,一直到結(jié)束。

Go 語言中 map 是基于 數(shù)組和鏈表 的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,通過 優(yōu)化的拉鏈法 解決哈希沖突,每個 bucket 可以保存 8 對鍵值,在 8 個鍵值對數(shù)據(jù)后面有一個 overflow 指針,因為桶中最多只能裝 8 個鍵值對,如果有多余的鍵值對落到了當前桶,那么就需要再構(gòu)建一個桶(稱為溢出桶),通過 overflow 指針鏈接起來。

因為 overflow 指針的緣故,所以無論 map 保存的是什么,GC 的時候就會把所有的 bmap 掃描一遍,帶來巨大的 GC 開銷。官方 issues 就有關(guān)于這個問題的討論, runtime: Large maps cause significant GC pauses #9477

無腦機翻如下:

如果我們有一個map [k] v,其中k和v都不包含指針,并且我們想提高掃描性能,則可以執(zhí)行以下操作。

將“ allOverflow [] unsafe.Pointer”添加到 hmap 并將所有溢出存儲桶存儲在其中。 然后將 bmap 標記為noScan。 這將使掃描非??欤驗槲覀儾粫呙枞魏斡脩魯?shù)據(jù)。

實際上,它將有些復雜,因為我們需要從allOverflow中刪除舊的溢出桶。 而且它還會增加 hmap 的大小,因此也可能需要重新整理數(shù)據(jù)。

最終官方在 hmap 中增加了 overflow 相關(guān)字段完成了上面的優(yōu)化,這是具體的 commit 地址。

下面看下具體是如何實現(xiàn)的,源碼基于 go1.15,src/cmd/compile/internal/gc/reflect.go 中

通過注釋可以看出,如果 map 中保存的鍵值都不包含指針(通過 Haspointers 判斷),就使用一個 uintptr 類型代替 bucket 的指針用于溢出桶 overflow 字段,uintptr 類型在 GO 語言中就是個大小可以保存得下指針的整數(shù),不是指針,就相當于實現(xiàn)了 將 bmap 標記為 noScan, GC 的時候就不會遍歷完整個 map 了。隨著不斷的學習,愈發(fā)感慨 GO 語言中很多模塊設計得太精妙了。

差不多說清楚了,能力有限,有不對的地方歡迎留言討論,源碼位置還是問的群里大佬 _

Golang|切片原理

在Golang語言開發(fā)過程中,我們經(jīng)常會用到數(shù)組和切片數(shù)據(jù)結(jié)構(gòu),數(shù)組是固定長度的,而切片是可以擴張的數(shù)組,那么切片底層到底有什么不同?接下來我們來詳細分析一下內(nèi)部實現(xiàn)。

首先我們來看一下數(shù)據(jù)結(jié)構(gòu)

這里的array其實是指向切片管理的內(nèi)存塊首地址,而len就是切片的實際使用大小,cap就是切片的容量。

我們可以通過下面的代碼輸出slice:

這么分析下來,我們可以了解如下內(nèi)容:

使用一個切片通常有兩種方法:

另一種是slice = make([]int, len, cap)這種方法,稱為分配內(nèi)存。

創(chuàng)建一個slice,實質(zhì)上是在分配內(nèi)存。

這里跟一下細節(jié),math.MulUintptr是基于底層的指針計算乘法的,這樣計算不會導致超出int大小,這個方法在后面會經(jīng)常用到。

同樣,對于int64的長度,也有對應的方法

而實際分配內(nèi)存的操作調(diào)用mallocgc這個分配內(nèi)存的函數(shù),這個函數(shù)以后再分析。

我們了解切片和數(shù)組最大的不同就是切片能夠自動擴容,接下來看看切片是如何擴容的

這里可以看到,growslice是返回了一個新的slice,也就是說如果發(fā)生了擴容,會發(fā)生拷貝。

所以我們在使用過程中,如果預先知道容量,可以預先分配好容量再使用,能提高運行效率。

copy這個函數(shù)在內(nèi)部實現(xiàn)為slicecopy

還有關(guān)于字符串的拷貝

這里顯示了可以把string拷貝成[]byte,不能把[]byte拷貝成string。

1、切片的數(shù)據(jù)結(jié)構(gòu)是 array內(nèi)存地址,len長度,cap容量

2、make的時候需要注意 容量 * 長度 分配的內(nèi)存大小要小于264,并且要小于可分配的內(nèi)存量,同時長度不能大于容量。

3、內(nèi)存增長的過程:

4、當發(fā)生內(nèi)存擴容時,會發(fā)生拷貝數(shù)據(jù)的現(xiàn)象,影響程序運行的效率,如果可以,要先分配好指定的容量

5、關(guān)于拷貝,可以把string拷貝成[]byte,不能把[]byte拷貝成string。


網(wǎng)站題目:go語言uintptr go語言適合做什么
URL網(wǎng)址:http://weahome.cn/article/ddpoohs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部