I have identified a bottleneck in my program, it is a buffered channel. I would like to give client an indication of system load, which should be indicated by number of messages buffered in the channel.
Is there a way in Go to tell how many buffered messages there are in a channel?
If you also have a Java background, I am looking for an equivelent of this: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html#size()
The built-in functions
len
andcap
take arguments of various types and return a result of typeint
. The implementation guarantees that the result always fits into anint
.Call Argument type Result len(s) chan T number of elements queued in channel buffer cap(s) chan T channel buffer capacity
The len
function for a channel gives the number of elements queued in the channel buffer. For example,
package main
import "fmt"
func main() {
ch := make(chan int, 8)
ch <- 42
ch <- 7
<-ch
ch <- 64
// number of queued elements = 1 + 1 - 1 + 1 = 2
fmt.Println(len(ch), cap(ch))
}
Output:
2 8
There is an alternative solution to this using a "queue" process that handles the queueing of messages and also is able to report on its size. For this you will need an input channel and an output channel, plus a query channel through which the size is obtained. Because there will be two input channels, you will need a select (a CSP 'choice') between them.
Here's a little demo of this in operation. The queue consists of a slice as a buffer and an input channel.
func queue(in <-chan string, out chan<- string, query <-chan chan int) {
buffer := []string{}
var s string
var reply chan int
for {
// Go select doesn't support boolean guards so we need the 'if' outside the select instead
if len(buffer) > 0 {
select {
case reply = <-query:
reply <- len(buffer)
case s = <-in:
buffer = append(buffer, s)
case out <- buffer[0]:
buffer = buffer[1:]
}
} else {
select {
case reply = <-query:
reply <- len(buffer)
case s = <-in:
buffer = append(buffer, s)
}
}
}
}