2015-06-10 16 views
6

Ich finde mich häufig Kanäle verwenden, um Dinge zu stoppen. In diesen Fällen wird der Kanal ausschließlich zur Signalisierung verwendet und keine der Daten wird tatsächlich verwendet.Welcher Kanaltyp verwendet am wenigsten Speicherplatz in Go?

Zum Beispiel:

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, wenn Sie auf dem golang Spielplatz gefallen.


Meine Frage ist:

Welche Kanaltyp hat die hellste Speicherbedarf in Go?

z.B. Wird ein bool chan weniger Aufwand benötigen als eine leere Struktur {} chan?

chan bool

chan byte

chan interface{}

chan struct{}

...

etwas anderes?

+2

Ich habe nicht in der Quelle verifiziert, aber ich würde erwarten, dass der Overhead des Kanals selbst den Effekt von Byte, Bool oder Struct {} für einen ungepufferten Kanal dominiert. – Volker

Antwort

6

am latest implementation des Kanals sucht, ist es keine triviale Struktur:

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 
} 

Elemente der Kellner Warteschlangen sind auch 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 
} 

Sie sehen, viele Bytes. Selbst wenn ein Element für einen leeren Kanal erstellt würde, wäre dies vernachlässigbar.

Ich erwarte jedoch, dass alle leeren Kanäle unabhängig vom zugrunde liegenden Typ den gleichen Speicherplatz beanspruchen. Wenn Sie also nur den Kanal schließen möchten, gibt es keinen Unterschied (ein tatsächliches Element scheint von a gehalten zu werden) Zeiger). Ein schneller Test sichert sie:

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

Ich sehe keinen Unterschied zwischen chan struct{} und chan [64000]byte, beiden Leitungen zu ~ 1 GB Nutzung auf meiner 64-Bit-Maschine, die ich irgendwo, dass Aufwand zur Erstellung eines einzelnen Kanals glauben macht ungefähr 100 Bytes.

Zusammenfassend ist es nicht wirklich wichtig. Persönlich würde ich struct{} verwenden, da es der einzige wirklich leere Typ ist (der Größe 0 in der Tat), klar anzeigend, dass keine Absicht ist, irgendeine Nutzlast zu senden.