精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Go高性能-兩種內(nèi)存大小為0的數(shù)據(jù)類(lèi)型

冬至子 ? 來(lái)源:洋芋土豆 ? 作者:真沒(méi)什么深度 ? 2023-05-22 17:33 ? 次閱讀

概述

Go 中的空結(jié)構(gòu)體 struct{}{} 的內(nèi)存大小等于 0,除此之外,還有別的數(shù)據(jù)類(lèi)型內(nèi)存大小也等于 0 嗎?

map 實(shí)現(xiàn) set

Go 的標(biāo)準(zhǔn)庫(kù)沒(méi)有內(nèi)置的 Set 類(lèi)型,在不引用第三方包的情況下,一般是結(jié)合內(nèi)置的 map 類(lèi)型實(shí)現(xiàn) Set 類(lèi)型相關(guān)功能。

這里假設(shè) Set 元素類(lèi)型為 int, 那么我們就以 int 作為 map 的鍵類(lèi)型,以 bool 作為 map 的值類(lèi)型 (之所以選擇 bool 類(lèi)型,是因?yàn)槠浯笮?1 個(gè)字節(jié),相對(duì)其他數(shù)據(jù)類(lèi)型可以節(jié)省內(nèi)存,當(dāng)然,也可以使用 byte 類(lèi)型,其大小同樣是 1 個(gè)字節(jié))。

package main

import "fmt"

// Set 類(lèi)型定義
type set map[int]bool

// 初始化一個(gè)新的 Set
func newSet() set {
    return make(set)
}

// 元素是否存在于與集合中
func (s set) contains(ele int) bool {
    _, ok := s[ele]
    return ok
}

// 添加元素到集合
func (s set) add(ele int) {
    s[ele] = true
}

// 從集合中刪除某個(gè)元素
func (s set) remove(ele int) {
    delete(s, ele)
}

func main() {
    s := newSet()

    fmt.Println(s.contains(100))
    s.add(100)
    fmt.Println(s.contains(100))
    s.remove(100)
    fmt.Println(s.contains(100))
}
$ go run main.go

# 輸出如下
false
true
false

上述示例代碼通過(guò)內(nèi)置類(lèi)型 map 實(shí)現(xiàn)了 set 類(lèi)型相關(guān)功能,美中不足的一點(diǎn)在于: 每個(gè)元素都要浪費(fèi)一個(gè) bool 類(lèi)型作為標(biāo)識(shí)占位符, 能否進(jìn)一步的優(yōu)化呢 ?當(dāng)然是可以的,這就是接下來(lái)要講到的 空結(jié)構(gòu)體 了。

空結(jié)構(gòu)體

Go 中的空結(jié)構(gòu)體 struct{}{}一個(gè)底層的內(nèi)置變量,不占用任何內(nèi)存 :

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    fmt.Printf("size = %d\\n", unsafe.Sizeof(struct{}{}))
}
$ go run main.go

# 輸出如下
size = 0

結(jié)合剛才的例子,可以將 struct{}{} 作為 Set 的元素,這樣不論 Set 有多少個(gè)元素,標(biāo)志位 內(nèi)存占用始終為 0 。

使用 bool 實(shí)現(xiàn) Set

測(cè)試代碼

package performance

import (
    "testing"
)

// Set 類(lèi)型定義, 使用 bool 類(lèi)型作為占位符
type set map[int]bool

// 初始化一個(gè)新的 Set
func newSet() set {
    return make(set)
}

// 元素是否存在于與集合中
func (s set) contains(ele int) bool {
    _, ok := s[ele]
    return ok
}

// 添加元素到集合
func (s set) add(ele int) {
    s[ele] = true
}

// 從集合中刪除某個(gè)元素
func (s set) remove(ele int) {
    delete(s, ele)
}

func Benchmark_Compare(b *testing.B) {
    s := newSet()

    for i := 0; i < b.N; i++ {
        s.add(i)
    }
    for i := 0; i < b.N; i++ {
        _ = s.contains(i)
        s.remove(i)
    }
}

運(yùn)行測(cè)試,并將基準(zhǔn)測(cè)試結(jié)果寫(xiě)入文件:

$ go test -run='^$' -bench=. -count=1 -benchtime=10000000x -benchmem > bool.txt

使用空結(jié)構(gòu)體實(shí)現(xiàn) Set

測(cè)試代碼

package performance

import (
    "testing"
)

// Set 類(lèi)型定義, 使用 bool 類(lèi)型作為占位符
type set map[int]struct{}

// 初始化一個(gè)新的 Set
func newSet() set {
    return make(set)
}

// 元素是否存在于與集合中
func (s set) contains(ele int) bool {
    _, ok := s[ele]
    return ok
}

// 添加元素到集合
func (s set) add(ele int) {
    s[ele] = struct{}{}
}

// 從集合中刪除某個(gè)元素
func (s set) remove(ele int) {
    delete(s, ele)
}

func Benchmark_Compare(b *testing.B) {
    s := newSet()

    for i := 0; i < b.N; i++ {
        s.add(i)
    }
    for i := 0; i < b.N; i++ {
        _ = s.contains(i)
        s.remove(i)
    }
}

運(yùn)行測(cè)試,并將基準(zhǔn)測(cè)試結(jié)果寫(xiě)入文件:

$ go test -run='^$' -bench=. -count=1 -benchtime=10000000x -benchmem > struct.txt

使用 benchstat 比較差異

$ benchstat -alpha=100 bool.txt struct.txt

# 輸出如下
name        old time/op    new time/op    delta
_Compare-8     371ns ± 0%     332ns ± 0%  -10.47%  (p=1.000 n=1+1)

name        old alloc/op   new alloc/op   delta
_Compare-8     44.0B ± 0%     40.0B ± 0%   -9.09%  (p=1.000 n=1+1)

name        old allocs/op  new allocs/op  delta
_Compare-8      0.00           0.00          ~     (all equal)

從輸出的結(jié)果中可以看到,相比于使用 bool 作為 Set 元素占位符,使用 空結(jié)構(gòu)體 在性能和內(nèi)存占用方面,都有了小幅度的優(yōu)化提升 (10% 左右)。因?yàn)闀r(shí)間關(guān)系,這里的基準(zhǔn)測(cè)試只運(yùn)行了 10000000 次, 運(yùn)行次數(shù)越大,優(yōu)化的效果越明顯 。感興趣的讀者可以將 -benchtime 調(diào)大后看看優(yōu)化效果。

小結(jié)

**Go 中的空結(jié)構(gòu)體 **struct{}{} 不占用任何內(nèi)存,而且有很清晰的語(yǔ)義性質(zhì) (作為占位符使用) 。除了剛才示例中實(shí)現(xiàn) Set 類(lèi)型功能外, 還可以使用空結(jié)構(gòu)體作為 通道信號(hào)標(biāo)識(shí)空對(duì)象 等,各種使用場(chǎng)景請(qǐng)讀者自行探索。

彩蛋

除了空結(jié)構(gòu)體 struct{}{} 之外,還有一個(gè)鮮為人知的內(nèi)存大小為 0 的數(shù)據(jù)類(lèi)型是: 空數(shù)組。但是相對(duì) struct{}{} 豐富的表達(dá)性,空數(shù)組 使用的場(chǎng)景很少。

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    fmt.Printf("size = %d\\n", unsafe.Sizeof([0]int{}))
}
$ go run main.go

# 輸出如下
size = 0
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • go語(yǔ)言
    +關(guān)注

    關(guān)注

    1

    文章

    158

    瀏覽量

    9028
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    LabVIEW的數(shù)據(jù)類(lèi)型、存儲(chǔ)格式

    ,左邊的數(shù)字代表偏移(offset)數(shù)組在內(nèi)存起始存儲(chǔ)位置的字節(jié)數(shù)。其他數(shù)據(jù)類(lèi)型布爾、字符串、字符串?dāng)?shù)組、簇、路徑布爾(Boolean)型數(shù)據(jù)是字節(jié)型數(shù)據(jù),存儲(chǔ)
    發(fā)表于 12-19 15:36

    LabVIEW的數(shù)據(jù)類(lèi)型、存儲(chǔ)格式

    ,左邊的數(shù)字代表偏移(offset)數(shù)組在內(nèi)存起始存儲(chǔ)位置的字節(jié)數(shù)。其他數(shù)據(jù)類(lèi)型布爾、字符串、字符串?dāng)?shù)組、簇、路徑布爾(Boolean)型數(shù)據(jù)是字節(jié)型數(shù)據(jù),存儲(chǔ)
    發(fā)表于 12-19 15:37

    Python中常用的數(shù)據(jù)類(lèi)型

    字符串在Python中,加了引號(hào)的字符都被認(rèn)為是字符串,其聲明有三方式,分別是:?jiǎn)我?hào)、雙引號(hào)和三引號(hào);Python中的字符串有兩種數(shù)據(jù)類(lèi)型,分別是str類(lèi)型和unicode類(lèi)型
    發(fā)表于 04-19 15:14

    STM32F103xx系列內(nèi)存大小

    系列內(nèi)存大小三、閃存概述四、寫(xiě)和擦除閃存五、讀操作六、總代碼實(shí)現(xiàn)一、內(nèi)存大小內(nèi)存的容量一般都是 2的整次方倍,系統(tǒng)對(duì)內(nèi)存的識(shí)別是以Byte(字節(jié))
    發(fā)表于 08-19 08:53

    電腦內(nèi)存大小怎么查看

    日常辦公或者玩游戲的時(shí)候,都需要確認(rèn)一下電腦內(nèi)存夠不夠運(yùn)行將要辦公的軟件或者將要玩游戲的軟件,問(wèn)題來(lái)了,怎么查看電腦內(nèi)存大小?現(xiàn)在給大家?guī)?lái)怎么查看電腦內(nèi)存大小教程。
    發(fā)表于 05-27 10:13 ?3409次閱讀

    Linux:測(cè)試進(jìn)程占用的虛擬內(nèi)存大小

    Linux:測(cè)試進(jìn)程占用的虛擬內(nèi)存大小
    的頭像 發(fā)表于 06-23 09:23 ?2856次閱讀
    Linux:測(cè)試進(jìn)程占用的虛擬<b class='flag-5'>內(nèi)存大小</b>

    c++ 之布爾類(lèi)型和引用的學(xué)習(xí)總結(jié)

    在c語(yǔ)言里面我們知道是沒(méi)有布爾數(shù)據(jù)類(lèi)型的,而在C++中添加了布爾數(shù)據(jù)類(lèi)型(bool),它的取值是:true或者false(也就是1或者0),在內(nèi)存大小上它占用一個(gè)字節(jié)
    的頭像 發(fā)表于 12-24 18:03 ?569次閱讀

    重視變量的數(shù)據(jù)類(lèi)型

    不管在什么語(yǔ)言中,定義一個(gè)變量時(shí)必然要在內(nèi)存中開(kāi)辟一個(gè)相應(yīng)大小的空間來(lái)存儲(chǔ)該變量。不同的數(shù)據(jù)類(lèi)型內(nèi)存所占的空間大小不同,其所能表示的
    發(fā)表于 01-13 15:05 ?1次下載
    重視變量的<b class='flag-5'>數(shù)據(jù)類(lèi)型</b>

    C語(yǔ)言中內(nèi)存四區(qū)模型的本質(zhì)區(qū)別和代碼分析

    數(shù)據(jù)類(lèi)型可理解創(chuàng)建變量的模具:是固定內(nèi)存大小的別名。
    的頭像 發(fā)表于 03-09 14:45 ?1031次閱讀

    什么是數(shù)據(jù)類(lèi)型轉(zhuǎn)換

    常用的3種數(shù)據(jù)類(lèi)型:1、Python數(shù)據(jù)類(lèi)型第一:字符串(str)。 2、Python數(shù)據(jù)類(lèi)型第二:整數(shù)(int)。 3、Pytho
    的頭像 發(fā)表于 02-23 15:21 ?1746次閱讀

    CODESYS變量類(lèi)型的范圍和所占內(nèi)存大小

    在使用通訊和數(shù)據(jù)類(lèi)型轉(zhuǎn)換時(shí),需要特別注意數(shù)據(jù)類(lèi)型的范圍和所占存儲(chǔ)空間的大小,為了方便查詢(xún),在這里和大家歸納總結(jié)下。
    的頭像 發(fā)表于 05-25 14:57 ?5869次閱讀
    CODESYS變量<b class='flag-5'>類(lèi)型</b>的范圍和所占<b class='flag-5'>內(nèi)存大小</b>

    Verilog最常用的2種數(shù)據(jù)類(lèi)型

    Verilog 最常用的 2 種數(shù)據(jù)類(lèi)型就是線網(wǎng)(wire)與寄存器(reg),其余類(lèi)型可以理解兩種數(shù)據(jù)類(lèi)型的擴(kuò)展或輔助。
    的頭像 發(fā)表于 05-29 16:27 ?2202次閱讀
    Verilog最常用的2<b class='flag-5'>種數(shù)據(jù)類(lèi)型</b>

    redis的五種數(shù)據(jù)類(lèi)型

    Redis是一高性能內(nèi)存數(shù)據(jù)庫(kù),常用于緩存、任務(wù)隊(duì)列、分布式鎖等場(chǎng)景。它提供了多種數(shù)據(jù)類(lèi)型來(lái)滿(mǎn)足各種不同的需求,包括字符串(string
    的頭像 發(fā)表于 11-16 11:06 ?603次閱讀

    weblogic設(shè)置jvm內(nèi)存大小

    WebLogic是一Java EE應(yīng)用服務(wù)器,用于構(gòu)建和部署企業(yè)級(jí)Java應(yīng)用程序。在配置WebLogic服務(wù)器時(shí),設(shè)置JVM的內(nèi)存大小非常重要,這可以提高應(yīng)用程序的性能和可靠性。本文將詳細(xì)介紹
    的頭像 發(fā)表于 12-05 14:44 ?2972次閱讀

    eclipse設(shè)置jvm內(nèi)存大小

    內(nèi)存大小,并對(duì)其背后的原理進(jìn)行解釋。 JVM(Java虛擬機(jī))是Java程序的運(yùn)行環(huán)境,它負(fù)責(zé)將Java字節(jié)碼翻譯成機(jī)器碼,以便在不同的平臺(tái)上執(zhí)行。JVM使用內(nèi)存來(lái)存儲(chǔ)運(yùn)行時(shí)對(duì)象和執(zhí)行過(guò)程中的臨時(shí)數(shù)據(jù)。如果JVM的
    的頭像 發(fā)表于 12-06 11:43 ?1818次閱讀