Какой тип канала использует наименьший объем памяти в Go?

Я часто использую каналы, чтобы остановить вещи. В этих случаях канал используется исключительно как средство сигнализации, и ни одна из данных фактически не используется.

например:

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

запустить/посмотреть это пожалуйста, на игровой площадке golang.


мой вопрос:

какой тип канала имеет самый легкий след памяти в Go?

например, идет ли bool chan требовать меньше накладных расходов, чем пустая структура{} chan?

chan bool

chan byte

chan interface{}

chan struct{}

...

что-то еще?

1 ответов


смотреть на!--7-->последний реализации канала, это не тривиальная структуру:

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
}

элементы очередей официантов также очень тяжелый:

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, оба приводят к ~1GB использования на моей 64-битной машине, что заставляет меня полагать, что накладные расходы на создание одного канала где-то около 100 байт.

В заключение, это действительно не имеет значения. Лично я бы использовал struct{} поскольку это единственный действительно пустой тип (размер 0 действительно), четко указывая на отсутствие намерения любой груз отправили.