dongyan0629 2015-06-10 21:19
浏览 62
已采纳

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

I find myself frequently using channels to get things to stop. In these cases the channel is being used solely as a means of signaling, and none of the data is actually used.

For example:

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 if you please on the golang playground.


My question is:

Which channel type has the lightest memory footprint in Go?

e.g. Is a bool chan going to require any less overhead than an empty struct{} chan?

chan bool

chan byte

chan interface{}

chan struct{}

...

something else?

  • 写回答

1条回答 默认 最新

  • douyu1990 2015-06-10 23:20
    关注

    Looking at the latest implementation of the channel, it's not a trivial structure:

    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
    }
    

    Elements of waiter queues are also 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
    }
    

    You see, many bytes. Even if any element would be created for an empty channel, this would be negligible.

    However, I expect all empty channels to take the same amount of space, regardless of underlying type, so if you intend to only close the channel, there'll be no difference (an actual element seems to be hold by a pointer). A quick test backs it up:

    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)
    }
    

    I see no difference between chan struct{} and chan [64000]byte, both leads to ~1GB of usage on my 64-bit machine, which makes me believe that overhead of creating a single channel in somewhere around 100 bytes.

    In conclusion, it doesn't really matter. Personally I would use struct{} as it's the only really empty type (of size 0 indeed), clearly indicating there is no intension of any payload being sent.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看