Reporting Real-time Performance of Channels
--
Go ships with great tools for runtime performance monitoring. However, for one of the projects I am working on I needed tailored metrics around three channels that do the primary communication between the larger components of the processing service.
I wanted to be able to print realtime stats on movement and blocking of these channels only each minute. So I created ChannelPerf
:
https://gist.github.com/elliotchance/7db9eb40a935f5526b62f0bcf77b7d2c
How does it work?
For the most part it is a drop in replacement-ish with how you would normally use a channel:
// ch := make(chan interface{}, 1)
ch := NewChannelPerf(1, "Some name")// ch <- "foo"
ch.Send("foo")// next, ok := <-ch
next, ok := ch.Receive()// close(ch)
ch.Close()// for next := range ch {
// fmt.Println(next)
// }
for {
next, ok := ch.Receive()
if !ok {
break
} fmt.Println(next)
}
The name (second parameter of NewChannelPerf
) is used to label statistics with ch.String()
:
fmt.Println(ch)
Displays something like:
Some name (clock: 1.387381ms, sent: 3 in 1.745µs, received: 3 in 1.268469ms)
clock
is how long it has been tracking statistics. Statistics can be reset withch.Reset()
sent
is the number of messages successfully sent to the channel, and the total time waiting (blocking) to do so. If the channel is full and goroutine(s) are blocked trying to send to the channel, this time will increase.received
is the number of messages successfully received from the channel (unrelated to how many messages may be available), and how long it was waiting on receiving. If the channel is empty and goroutine(s) are blocked waiting then this time will increase.- One important thing to note is that the
sent
andreceived
are total times, not actual times. For example, if there are 3 goroutines blocked on sending, once sent the time will be the addition of all of these. If you only have one goroutine on either side of the channel that’s easy. However, you…