【问题标题】:Which channel type uses the least amount of memory in Go?Go 中哪种通道类型使用的内存最少?
【发布时间】:2015-08-26 08:45:09
【问题描述】:

我发现自己经常使用渠道来阻止事情。在这些情况下,通道仅被用作一种信号方式,实际上并没有使用任何数据。

例如:

package main

import (
    "fmt"
    "time"
)

func routine(stopChan chan bool) {
    fmt.Println("goroutine: I've started!")
    <-stopChan
    fmt.Println("goroutine: Cya'round pal")
}

func main() {
    fmt.Println("main: Sample program run started")

    stopChan := make(chan bool)

    go routine(stopChan)

    fmt.Println("main: Fired up the goroutine")

    stopChan <- true

    time.Sleep(1 * time.Second)

    fmt.Println("main: Sample program run finished")
}

// Sample output:
//
//  main: Sample program run started
//  main: Fired up the goroutine
//  goroutine: I've started!
//  goroutine: Cya'round pal
//  main: Sample program run finished

Run/view it 请在 golang 操场上。


我的问题是:

Go 中哪种通道类型的内存占用最少?

例如bool chan 需要的开销是否会比空 struct{} chan 少?

chan bool

chan byte

chan interface{}

chan struct{}

...

还有什么?

【问题讨论】:

  • 我没有在源代码中进行验证,但我预计通道本身的开销会主导无缓冲通道的 byte、bool 或 struct{} 效果。

标签: memory go resources channel internals


【解决方案1】:

看频道的latest implementation,不简单的结构:

type hchan struct {
    qcount   uint           // total data in the queue
    dataqsiz uint           // size of the circular queue
    buf      unsafe.Pointer // points to an array of dataqsiz elements
    elemsize uint16
    closed   uint32
    elemtype *_type // element type
    sendx    uint   // send index
    recvx    uint   // receive index
    recvq    waitq  // list of recv waiters
    sendq    waitq  // list of send waiters
    lock     mutex
}

服务员队列的元素也是quite heavy:

type sudog struct {
    g           *g
    selectdone  *uint32
    next        *sudog
    prev        *sudog
    elem        unsafe.Pointer // data element
    releasetime int64
    nrelease    int32  // -1 for acquire
    waitlink    *sudog // g.waiting list
}

你看,很多个字节。即使会为空通道创建任何元素,这也可以忽略不计。

但是,我希望所有空通道占用相同数量的空间,无论底层类型如何,因此如果您打算只关闭通道,则没有区别(实际元素似乎由指针持有)。快速测试支持它:

package main

import (
    "fmt"
    "time"
)

func main() {
    // channel type
    type xchan chan [64000]byte
    a := make([]xchan, 10000000) // 10 million
    for n := range a {
        a[n] = make(xchan)
    }
    fmt.Println("done")
    time.Sleep(time.Minute)
}

我认为chan struct{}chan [64000]byte 之间没有区别,两者都导致在我的 64 位机器上使用约 1GB,这让我相信在大约 100 字节的地方创建单个通道的开销。

总之,这并不重要。就我个人而言,我会使用struct{},因为它是唯一真正空的类型(确实是大小为 0),清楚地表明没有任何有效载荷被发送的意图。

【讨论】:

    猜你喜欢
    • 2013-08-10
    • 2018-11-12
    • 2016-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多