0

I was using time.After(time), which is working OK.

My question is: Is it precise and should I use this or should I make my own function? I am using this with a Raft Consensus algorithm implementation.

nemo
  • 55,207
  • 13
  • 135
  • 135
  • depends on what you mean by accurate. There is overhead to creating the timer, channel, and calling the function, so calling nanosecond-level intervals isn't too useful. – JimB Mar 08 '14 at 16:48
  • 1
    It is more precise than you would reasonably be able to create yourself, as time.After() has a bit of magic and ties down to the runtime eventloop, using non-public APIs. – nos Mar 11 '14 at 00:29
  • if you need to shave off a little overhead (200ns an 2 allocs on my system), you can create the a timer ahead of time, and reuse it instead of calling time.After – JimB Mar 11 '14 at 15:39

1 Answers1

4

I presume you mean time.After?

I wrote a quick benchmark to answer this question.

Run with go test -run XXX -bench . time_after_test.go

package main

import (
    "testing"
    "time"
)

func BenchmarkTimeAfterSecond(b *testing.B) {
    for i := 0; i < b.N; i++ {
        <-time.After(time.Second)
    }
}

func BenchmarkTimeAfterMillisecond(b *testing.B) {
    for i := 0; i < b.N; i++ {
        <-time.After(time.Millisecond)
    }
}

func BenchmarkTimeAfterMicrosecond(b *testing.B) {
    for i := 0; i < b.N; i++ {
        <-time.After(time.Microsecond)
    }
}

func BenchmarkTimeAfterNanosecond(b *testing.B) {
    for i := 0; i < b.N; i++ {
        <-time.After(time.Nanosecond)
    }
}

This gave this under go1.2 on a linux amd64 machine

BenchmarkTimeAfterSecond                   1    1000132210 ns/op
BenchmarkTimeAfterMillisecond           2000       1106763 ns/op
BenchmarkTimeAfterMicrosecond          50000         62649 ns/op
BenchmarkTimeAfterNanosecond         5000000           493 ns/op

So the answer is accurate to 0.1-0.2 mS or so on my machine.

This is extremely OS and hardware dependent though so will vary on your OS and hardware of choice.

Nick Craig-Wood
  • 52,955
  • 12
  • 126
  • 132
  • you don't need a select around a single channel read, you're just adding to the overhead. – JimB Mar 08 '14 at 16:45
  • @JimB good point... however it makes only about 6 ns difference on my machine when I tested it just now. – Nick Craig-Wood Mar 08 '14 at 22:03
  • People come to SO for examples of ways to do things. Wrapping a single channel receive in a select block may not have a tremendous performance impact, but it's a lot of unnecessary complexity you're putting in front of already confused users. – Dustin Mar 09 '14 at 08:47
  • @Dustin I'm almost certain that the OP is using `select` for making timeouts as it is the way it is done in Go, just with more `case` statements. That is why I wrote it like that anyway. – Nick Craig-Wood Mar 09 '14 at 10:01
  • Then your benchmark would be more accurate for that case if it also included a receive from a channel that wasn't ready to send. I'd also include a case for nil, as well as a case where the timeout doesn't fire, which would be catastrophic in these short timeout cases. – Dustin Mar 09 '14 at 17:22
  • well, this is all moot anyway, since OP hasn't provided any code, and we don't know what he means by "precise". – JimB Mar 10 '14 at 14:06
  • what about the cooperative scheduling of the go-routine so if one is busy in doing computation then it will not handover the execution to other go-routine and then it will starve other go routine (it might possible there is one go-routine that is received timeout that can be delayed.. it happened with my program) – Yogender Solanki Mar 11 '14 at 11:03
  • @YogenderSolanki, Go isn't realtime, so you have to accept the limitations of the runtime. That said, if you have a busy loop where you're not calling any functions, and you're starving other goroutines, and you can add a runtime.GoSched. This has nothing to do with timers, and you're still not going to be able to create a timer any better than the builtin time.Timer. – JimB Mar 11 '14 at 15:32
  • thanks.. i was hoping that there is another option exist @JimB – Yogender Solanki Mar 11 '14 at 17:46