In-depth discussion of channel timeout

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

The Go language channel itself does not support timeout, so the general implementation of the channel read and write timeout using Select, as follows:

select {case <-c:case <-time.After(time.Second):}

Is it really good that these two days were suddenly skeptical of the way the channel timed out during the code-writing process? So I wrote a test program like this:

package mainimport (    "os"    "time")func main() {    c := make(chan int, 100)    go func() {        for i := 0; i < 10; i++ {            c <- 1            time.Sleep(time.Second)        }        os.Exit(0)    }()    for {        select {        case n := <-c:            println(n)        case <-timeAfter(time.Second * 2):        }    }}func timeAfter(d time.Duration) chan int {    q := make(chan int, 1)    time.AfterFunc(d, func() {        q <- 1        println("run") // 重点在这里    })    return q}

This program is very simple, you will find that the results will be output 10 "run", that is, every time the select registered timer is executed, although there is no time to read the channel timeout. The reason is actually very simple, each execution of the SELECT statement, the case condition statement will be executed once, so timeafter execution result is to create a timer, and registered to runtime, the SELECT statement after the completion of the execution, the timer itself is not revoked, Also continues to remain in the runtime's small top heap, so the timer executes the mounted function once the timeout is exceeded.

Of course, using time.After() the function to do the channel read and write timeout, in the application layer can not feel at the bottom of the timer is still retained, continue to execute; The problem is that if the SELECT statement here executes very quickly in the loop, that is, the message in the channel is very frequent, the problem is There will be a large number of timers in runtime, the longer the timeout is set, the more timers will be maintained at the bottom. The reason is that each time a select selects a new timer, and the timer is deleted only after it has timed out.

Consider that your channel will transmit thousands of messages per second, and how many timer objects will exist in the underlying runtime. Will a large number of temporary objects affect memory? Will a large number of timers affect the accuracy of the rest of the timer?

Finally, I think the right channel timeout might be the way to do it:

to := time.NewTimer(time.Second)for {    to.Reset(time.Second)    select {    case <-c:    case <-to.C:    }}

This is done in order to maintain a single global timer, adjust the timer time-out before each operation, so as to avoid generating a new timer object for each cycle.

A simple test of the two channel time-out implementations, in full power to send and receive data in the case of memory objects and GC conditions.

* The Blue Line is used time.After() , and set the number of heap memory objects allocated by 4s timeout * The Green Line is adopted and set the number of time.After() heap memory objects allocated by 2s timeout * Yellow Line is the number assigned by the heap memory object with global timer and set 4s timeout

This phenomenon is in fact expected, the focus can be noted that the longer the timeout period, time.After() the performance will be worse.



The three lines and the three lines describe the same object, and the GC time in the figure is the average time of each GC.

For this channel timeout, I did not go to test whether it would affect the accuracy of other timers, but I think it is inevitable, with the increase in timers.

Finally, I have always felt that the channel itself should support the timeout mechanism rather than using SELECT.

The most interesting thing is to explore the real reason behind any phenomenon.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.