Buffered Channel's Performance

1,328 views
Skip to first unread message

Gyu-Ho Lee

unread,
Dec 1, 2013, 4:24:21 PM12/1/13
to golan...@googlegroups.com
I've benchmarking this go tour example with buffered channel.


The original example goes like this.

    c := make(chan int)
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    x, y := <-c, <-c



And for my benchmarking, I give a large numbers with rand package. And try to compare this unbuffered channel with buffered one.
My buffered channel would be like this so that when another goroutine tries to send, it does not block.

    c := make(chan int, 2)
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    x, y := <-c, <-c


Doesn't it mean that buffered channel should perform faster than unbuffered because there is no wait-time that is blocking? 

It is hard to find a concrete example of benefit of using buffered channels.

Gyu-Ho Lee

unread,
Dec 1, 2013, 4:34:41 PM12/1/13
to golan...@googlegroups.com
Typo: I've [been] benchmarking / I give [ large numbers ]

simon place

unread,
Dec 1, 2013, 5:41:54 PM12/1/13
to golan...@googlegroups.com
are you turning on multiprocessor support?


ie  runtime.GOMAXPROCS(runtime.NumCPU())

without it they are still done, underneath, one after another


Gyu-Ho Lee

unread,
Dec 1, 2013, 5:49:44 PM12/1/13
to golan...@googlegroups.com
Yes, the full code is here. http://play.golang.org/p/8OAbtn6koN

And for benchmarking, like the following link


var resultchSumBuffer int

func BenchmarkchSumBuffer(b *testing.B) {
runtime.GOMAXPROCS(runtime.NumCPU())
var r int
for i := 0; i < b.N; i++ {
sum, _ := chSumBuffer(2000000)
r = sum
}
resultchSumBuffer = r

felix...@gmail.com

unread,
Dec 1, 2013, 5:56:20 PM12/1/13
to golan...@googlegroups.com
Yes, because buffered channels don't wait, so u should see some performance increase
when using it.(but it might not alway be true it depends on what your code is doing)

Gyu-Ho Lee

unread,
Dec 1, 2013, 6:03:22 PM12/1/13
to golan...@googlegroups.com
Thanks, I might keep looking for the example, since mine is not really showing the performance increase with buffered channel.

Dave Cheney

unread,
Dec 1, 2013, 6:05:29 PM12/1/13
to Gyu-Ho Lee, golang-nuts
On Mon, Dec 2, 2013 at 9:49 AM, Gyu-Ho Lee <gyuh...@gmail.com> wrote:
> Yes, the full code is here. http://play.golang.org/p/8OAbtn6koN
>
> And for benchmarking, like the following link
>
> http://play.golang.org/p/JK3yL4QwOJ
>
>
> It goes like this
>
> var resultchSumBuffer int
>
> func BenchmarkchSumBuffer(b *testing.B) {
> runtime.GOMAXPROCS(runtime.NumCPU())

Don't do it like that, use

go test -bench=. -cpu=1,2,4


> var r int
> for i := 0; i < b.N; i++ {
> sum, _ := chSumBuffer(2000000)
> r = sum
> }
> resultchSumBuffer = r
> }
>
>
>
> On Sunday, December 1, 2013 2:41:54 PM UTC-8, simon place wrote:
>>
>> are you turning on multiprocessor support?
>>
>>
>> ie runtime.GOMAXPROCS(runtime.NumCPU())
>>
>> without it they are still done, underneath, one after another
>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

Gyu-Ho Lee

unread,
Dec 1, 2013, 6:14:47 PM12/1/13
to golan...@googlegroups.com
Thanks, Dave!

felix...@gmail.com

unread,
Dec 1, 2013, 6:16:47 PM12/1/13
to golan...@googlegroups.com
you might not see it with small code
run it yourself

Jesse McNelis

unread,
Dec 1, 2013, 6:20:02 PM12/1/13
to felix...@gmail.com, golang-nuts
On Mon, Dec 2, 2013 at 9:56 AM, <felix...@gmail.com> wrote:
Yes, because buffered channels don't wait, so u should see some performance increase
when using it.(but it might not alway be true it depends on what your code is doing)

Waiting isn't a problem if you've got something else to do while you wait.
I'm currently waiting for the kettle to boil and writing this email.
If the kettle boiled instantly, I'd still be writing this email and I'd still complete the email and drink my coffee in the same amount of time.

--
=====================
http://jessta.id.au

Gyu-Ho Lee

unread,
Dec 1, 2013, 6:22:50 PM12/1/13
to golan...@googlegroups.com
Thanks, I will play around with your code. Great.

Gyu-Ho Lee

unread,
Dec 1, 2013, 6:31:28 PM12/1/13
to golan...@googlegroups.com, felix...@gmail.com
http://play.golang.org/p/Ki8Xz9InM1

"note when is not buffered there is only one name"

But as long as we make sure close the channel, unbuffered channel also can contain all 7 strings. Look at my example.
 Thanks

felix...@gmail.com

unread,
Dec 1, 2013, 6:41:28 PM12/1/13
to golan...@googlegroups.com, felix...@gmail.com
Lee don't forget channel block, so on line 12 of your implementation
when you send into the channel it blocks for it to be read.

Harald Weidner

unread,
Dec 1, 2013, 7:16:45 PM12/1/13
to golan...@googlegroups.com
Hello,

>I've benchmarking this go tour example with buffered channel.
>http://tour.golang.org/#64

>Doesn't it mean that buffered channel should perform faster than unbuffered
>because there is no wait-time that is blocking?

What exactly are you trying to measure?

The difference between unbuffered and buffered channels is that with a
buffered channel, the sender does not block even if the receiver is
not ready to receive, unless the buffer is full.

In this example, each goroutine exits directly after sending. Moreover,
the receiver is always ready, because it does not expect the messages
in a specific order. Thus, changing from unbuffered to buffered channels
makes no difference for the performance of the example.

As the example splits up the sum calculation into two goroutines, setting
-cpu=2 (or higher) should be faster than 1, if you system has 2 or more
cpu cores. However, the most cpu time is spent in the creation of the
slice, which is non-parallelized.

>It is hard to find a concrete example of benefit of using buffered channels.

Consider a program witch works on jobs in a pipeline. Each job has to run
through each step of the pipeline sequentially. The pipeline steps are
implemented as goroutines, and the jobs are submitted through channels.
Each step take the same time in average, but time varies from job to job.

With unbuffered channels, a pipeline step must wait for the next step
to become ready, and cannot work on the next job in the meantime. Buffered
channel allow to store intermediate results in the buffer, which leads
to a better utilization in summary.

See http://play.golang.org/p/5PVZfaq4-m for an example implementation with
3 pipeline steps, which take between 0 and 100 milliseconds for each step.
The program runs measurably faster when "make(chan int)" is replaced by e.g.
"make(chan int, 10)".

(You need to execute the program locally, because of the playgrounds
cache.)

Harald

Gyu-Ho Lee

unread,
Dec 1, 2013, 7:23:42 PM12/1/13
to golan...@googlegroups.com
Thanks, yes you are right. My code spends too much resource creating slice. I just wanted to see whether the NON-blocking of buffered channel performs faster than unbuffered channel that has blocking. 

Thanks for the code. I am playing around it right now and seems like working as I expected.
Reply all
Reply to author
Forward
0 new messages