package main
import (
"time"
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
TestTicker(wg)
wg.Wait()
}
func TestTicker(wg sync.WaitGroup) {
calDuration := func(duration time.Duration) time.Duration {
now := time.Now()
return now.Truncate(duration).Add(duration).Sub(now)
}
go func(){
t := time.NewTimer(calDuration(time.Minute))
for {
<-t.C
fmt.Println(time.Now())
t.Reset(calDuration(time.Minute))
}
wg.Done()
}()
}
It sometimes happens to tick twice a minute as the duration may shrink. It's really strange. Could somebody help me. Thanks
I simply use waitgroup to hold the main function while calling TestTicker.
I'm running the test code on my MacOS
2018-07-19 14:36:00.003887996 +0800 CST m=+24.916092657
2018-07-19 14:37:00.002985076 +0800 CST m=+84.917119245
2018-07-19 14:38:00.001214551 +0800 CST m=+144.917278207
2018-07-19 14:39:00.000418561 +0800 CST m=+204.918411736
2018-07-19 14:39:59.999490194 +0800 CST m=+264.919412884
2018-07-19 14:40:00.000167519 +0800 CST m=+264.920090231
2018-07-19 14:40:59.99914446 +0800 CST m=+324.920996684
2018-07-19 14:41:00.000247228 +0800 CST m=+324.922099488
The timer accuracy can vary depending on your OS, hardware and CPU load. Virtual Machines seem particularly bad at providing accurate timers (see https://github.com/golang/go/issues/14410). Unfortunately, you do not mention in what environment you're running this code.
If you can live with the inaccuracies, and still need your code do do something at about a full minute, your code breaks because when the interval is too short (14:39:59.999490194 is only 500µs short of 14:40), calDuration will make it wait that few microseconds until the next full minute. In order to fix this you need to use Duration.Round instead of Duration.Truncate.
Also do not forget that t.C returns the time at which the timer fired, so you need to use this value in your call to calDuration (this also saves you a costly syscalls).
func TestTicker(wg *sync.WaitGroup) {
calDuration := func(now time.Time, duration time.Duration) time.Duration {
return now.Round(duration).Add(duration).Sub(now)
}
go func(){
t := time.NewTimer(calDuration(time.Now(), time.Minute))
for {
now := <-t.C
fmt.Println(now)
t.Reset(calDuration(now, time.Minute))
}
wg.Done()
}()
}
Another approach is to use time.Ticker from the standard library and issue an appropriate sleep before starting the ticker so that it ticks on a full minute:
func TestTicker(wg *sync.WaitGroup) {
go func(interval time.Duration) {
// wait until next time interval
now := time.Now()
time.Sleep(now.Truncate(interval).Add(interval).Sub(now))
// get time of first beat
now = time.Now()
// start the ticker
t := time.NewTicker(interval)
for {
fmt.Println(now)
now = <-t.C
}
wg.Done()
}(time.Minute)
}
Related
Let's look carefully at the Ticker example code in Go's time package:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
done := make(chan bool)
go func() {
time.Sleep(10 * time.Second)
done <- true
}()
for {
select {
case <-done:
fmt.Println("Done!")
return
case t := <-ticker.C:
fmt.Println("Current time: ", t)
}
}
}
With the interval adjusted to 1 second for convenience, after running the example enough times, we see an instance where the current time is never printed (or it would have only printed 9 times rather than 10):
Current time: 2020-06-10 12:23:51.189421219 -0700 PDT m=+1.000350341
Done!
Current time: 2020-06-10 12:23:52.193636682 -0700 PDT m=+1.000473686
Done!
Current time: 2020-06-10 12:23:53.199688564 -0700 PDT m=+1.000322824
Done!
Current time: 2020-06-10 12:23:54.204380186 -0700 PDT m=+1.000420293
Done!
Current time: 2020-06-10 12:23:55.21085129 -0700 PDT m=+1.000266810
Done!
Done!
Current time: 2020-06-10 12:23:57.220120615 -0700 PDT m=+1.000479431
Done!
Current time: 2020-06-10 12:23:58.226167159 -0700 PDT m=+1.000443199
Done!
Current time: 2020-06-10 12:23:59.231721969 -0700 PDT m=+1.000316117
Done!
When both the done and ticker.C channels are ready concurrently, we enter the realm of Go nondeterministic behavior:
A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.
I understand Go's design rationale for why select is non-deterministic. It mostly boils down to a problem the language does not venture to solve because doing so is generally hard and may lead users to write unknowingly racy code, and thus prioritized select and exercise left to the reader.
Let's assume that, for whatever reason, I'd like to ensure all pending ticks are consumed prior to winding down the program and printing Done!. Is there a general transformation that can be applied to this simple example to make it deterministic?
I tried adding another signal channel:
func main() {
ticker := time.NewTicker(time.Second)
stop := make(chan bool)
done := make(chan bool)
tick := make(chan time.Time)
go func() {
time.Sleep(1 * time.Second)
stop <- true
}()
go func() {
for t := range tick {
fmt.Println("Current time: ", t)
}
done <- true
}()
for {
select {
case <-stop:
ticker.Stop()
close(tick)
case t := <-ticker.C:
tick <- t
break
case <-done:
fmt.Println("Done!")
return
}
}
}
But it seems to preform worse...
Current time: 2020-06-10 13:23:20.489040642 -0700 PDT m=+1.000425216
Done!
Current time: 2020-06-10 13:23:21.495263288 -0700 PDT m=+1.000338902
Done!
Current time: 2020-06-10 13:23:22.501474055 -0700 PDT m=+1.000327127
Done!
Current time: 2020-06-10 13:23:23.503531868 -0700 PDT m=+1.000244398
Done!
Current time: 2020-06-10 13:23:24.510210786 -0700 PDT m=+1.000420955
Done!
Current time: 2020-06-10 13:23:25.516500359 -0700 PDT m=+1.000460986
Done!
Done!
Current time: 2020-06-10 13:23:27.527077433 -0700 PDT m=+1.000375330
Done!
Current time: 2020-06-10 13:23:28.533401667 -0700 PDT m=+1.000470273
Done!
panic: send on closed channel
goroutine 1 [running]:
main.main()
/home/dcow/Desktop/ticker-go/main2.go:29 +0x22f
Current time: 2020-06-10 13:23:30.547554719 -0700 PDT m=+1.000399602
Done!
Current time: 2020-06-10 13:23:31.55416725 -0700 PDT m=+1.000443683
Done!
Current time: 2020-06-10 13:23:32.56041176 -0700 PDT m=+1.000436364
Done!
Done!
Current time: 2020-06-10 13:23:34.572550584 -0700 PDT m=+1.000445593
Done!
Current time: 2020-06-10 13:23:35.578672712 -0700 PDT m=+1.000357330
Done!
Done!
Current time: 2020-06-10 13:23:37.590984117 -0700 PDT m=+1.000447504
Done!
We can't guarantee that we won't receive the stop message at the same time as we receive the final tick, so we've just shuffled the problem around to something that panics when it behaves "incorrectly" (which is marginally better than doing so silently). If we niled the tick channel, we'd devolve to the original case. And we still have cases where no tick is printed at all likely because it's possible we close the timer before it ever has a chance to fire..
How about a ready channel?
func main() {
ticker := time.NewTicker(time.Second)
tick := make(chan time.Time)
ready := make(chan bool, 1)
stop := make(chan bool)
done := make(chan bool)
go func() {
time.Sleep(1 * time.Second)
<-ready
stop <- true
}()
go func() {
for t := range tick {
fmt.Println("Current time: ", t)
}
done <- true
}()
for {
select {
case <-stop:
ticker.Stop()
close(tick)
case t := <-ticker.C:
select {
case ready<-true:
break
default:
}
tick <- t
break
case <-done:
fmt.Println("Done!")
return
}
}
}
This seems to work. It's somewhat involved with the addition of 3 new channels and an additional go routine, but it hasn't failed thus far. Is this pattern idiomatic in go? Are there general form strategies for applying this type of transformation in scenarios where you want to prioritize one of the select cases? Most advice I've come across is related to sequential and nested selects which don't really solve the problem.
Alternatively, is there a way to say "give me the list of ready channels so I can pick the order in which I process them"?
Edit:
Adding some clarifying remarks: I'm not interested in preserving ordering of concurrent operations. I agree that's a silly endeavor. I simply want to be able know if a selection of channels are ready to be processed and provide my own logic dictating what to do when multiple channels are ready concurrently. I'm essentially interested in a Go analog to POSIX select. And/or I'm interested in literature describing or common knowledge surrounding a generalized "convert non-deterministic select to deterministic select in Go" pattern.
e.g. Do people use the heap package and deposit data into a priority queue and ultimately read from that? Is there an x/reflect style package that implements a prioritized select using unsafe? Is there some simple pattern like, "Convert all selects with a single channel that should take priority into a dual channel style and forward the "done" request the the producer which in turn should terminate and close their channel then block on a channel range loop (kinda like my working solution)? Actually, lock on a shared condition variable for reasons x, y. etc..
If you need to pick one channel over another when both are enabled, then you can do a nested select. This will pick the high priority one over the low priority one if both channels are enabled at the beginning of select:
select {
case <-highPriority:
// Deal with it
default:
select {
case <-lowPriority:
// low priority channel
default:
}
}
If you have N channels with a priority ranking, then you can try selecting in a loop:
for _,channel:=range channels {
select {
case <-channel:
//
default:
}
}
This of course will be an approximation of what you need because it'll miss channel state changes that happen while it is looping. But it will prioritize channels based on their state at the beginning of the for loop.
Then there is reflect.Select, but that will not prioritize.
Unless the application has some known ordering between ready state of the ticker and done channels, it's impossible to ensure that the application processes the values from the channels in the order that the values are sent.
The application can ensure that values queued in ticker.C are received before a value from done by using nested select statements.
for {
select {
case t := <-ticker.C:
fmt.Println("Current time: ", t)
default:
// ticker.C is not ready for commination, wait for both
// channels.
select {
case <-done:
fmt.Println("Done!")
return
case t := <-ticker.C:
fmt.Println("Current time: ", t)
}
}
}
If the done communication is executed before a ready <-ticker.C communication in the inner select, then the two channels entered the ready state at almost the same time. Unless there's a requirement not stated in the question, this shouldn't make a difference to the application.
The application can nest a third select to give receive on ticker.C one last opportunity to execute before the function returns. This approach gives priority to the ticker when the two channels enter the ready state at almost the same time. I mention this for completeness, not because I recommend it. As I said in the previous paragraph, the first snippet of code in this answer should be good enough.
for {
select {
case t := <-ticker.C:
fmt.Println("Current time: ", t)
default:
// ticker.C is not ready for commination, wait for both
// channels.
select {
case <-done:
// Give communication on <-ticker.C one last
// opportunity before exiting.
select {
case t := <-ticker.C:
// Note that the ticker may have entered
// the ready state just after the done channel
// entered the state.
fmt.Println("Current time: ", t)
default:
}
fmt.Println("Done!")
return
case t := <-ticker.C:
fmt.Println("Current time: ", t)
}
}
}
This question already has answers here:
What is the "m" in timestamp and how to get timestamp without "m"?
(3 answers)
Closed 3 years ago.
"I'm trying to output the values of a channel , which received values from a struct, which should be a string and time. It outputs those two, but then it includes this strange line " +0300 +03 m=+0.001997101" after the time."
Tried many other things from fmt package, but still no help. Tried things from the time package too
package main
import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"time"
)
var wg sync.WaitGroup
type widget struct {
Label string
Time time.Time
}
func main() {
c := make(chan widget)
sc := make(chan os.Signal, 1)
done := make(chan bool, 1)
signal.Notify(sc, syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGHUP,
syscall.SIGKILL,
syscall.SIGSEGV,
)
go func() {
sig := <-sc
fmt.Println()
fmt.Println(sig)
done <- true
}()
go send(c)
go receive(c)
<-done
fmt.Println("Program exited")
}
func send(p chan<- widget) {
producer := widget{
"widget_id_34",
time.Now(),
}
p <- producer
}
//where im grtting the problem from i beilieve
func receive(c <-chan widget) {
out := <-c
fmt.Printf("%v", out)
//fmt.Fprintln(os.Stdout, <-c)
}
The m field is the monotonic time. Per the docs:
The canonical way to strip a monotonic clock reading is to use t = t.Round(0).
Doing so yields a time without a m value. The +0300 is the time zone offset, which is part of the time value (without it, the time value would be useless, because it would have a margin of error of +/- 23 hours).
I have this block of code that is supposed to wait 10 seconds before the program exits, but it only works if I add some sort of print something for it afterwards. Why is that? I want it to wait 10 seconds without having to uncomment that print statement.
func main() {
forever := make(chan bool)
go func() {
fmt.Println("why")
time.Sleep(10*time.Second)
//fmt.Println("here")
forever <- false
}()
fmt.Println("forever")
<- forever
}
This also works:
func main() {
forever := make(chan bool)
go func() {
fmt.Println("why")
time.Sleep(10*time.Second)
forever <- false
}()
fmt.Println(<- forever)
}
The following program does not wait for 10 seconds when it is run in Go playground:
package main
import (
"time"
)
func main() {
forever := make(chan bool)
go func() {
time.Sleep(10 * time.Second)
forever <- false
}()
<-forever
}
Technically, it's a "feature" of the playground. When everything is blocked waiting on time in the playground, time will artificially advance until things unblock... or it decides things really are deadlocked. See "Faking Time" section in the Golang Playground article.
I am trying to get my Go program to block forever, but nothing is working.
Here are some things I have tried:
package main
func main() {
select{}
}
and
package main
func main() {
ch := make(chan bool)
<-ch
}
and
package main
import "sync"
func main() {
var wg sync.WaitGroup
wg.Add(1)
wg.Wait()
}
Each time I get the same error: fatal error: all goroutines are asleep - deadlock!
I thought I have done this before easily. Am I able to get the go program to block forever?
Those methods would work if you spawned another goroutine (which was doing stuff other than blocking)
The immediate fix to your problem would be:
time.Sleep(math.MaxInt64)
which would sleep for ~300 years
For example, the main goroutine blocks forever,
package main
import (
"fmt"
"time"
)
func forever() {
for {
fmt.Println(time.Now().UTC())
time.Sleep(time.Second)
}
}
func main() {
go forever()
select {} // block forever
}
Output:
2017-08-05 02:50:10.138353286 +0000 UTC
2017-08-05 02:50:11.138504194 +0000 UTC
2017-08-05 02:50:12.138618149 +0000 UTC
2017-08-05 02:50:13.138753477 +0000 UTC
2017-08-05 02:50:14.13888856 +0000 UTC
2017-08-05 02:50:15.139027355 +0000 UTC
...
...
...
For the question "How to get a Go program to block forever" there's already answers that use a for loop or time.Sleep.
But I want to answer "How to get a Go program to block forever with a channel never receives a value".
package main
func main() {
ch := make(chan bool)
go func(c chan bool) {
for {
}
c <- true // Because c never receives true,
}(ch)
<-ch // thus ch waits forever.
}
I think the sample code above can help to understand why and when a Go program will block by a channel.
I am trying to measure execution time of funcWithUnpredictiveExecutionTime function.
func measureTime(expectedMs float64) (ok bool) {
t1 := time.Now()
funcWithUnpredictiveExecutionTime()
t2 := time.Now()
diff := t2.Sub(t1)
The measuring is fine when funcWithUnpredictiveExecutionTime works faster than I expected. But if it works slower than expectedMs the measuring will not stop right after expected amount of milliseconds passed.
Is it possible to stop time measuring when funcWithUnpredictiveExecutionTime works longer than expectedMs without waiting funcWithUnpredictiveExecutionTime to finish?
In other words, measureTime(200) should return in 200 ms anyway with a good or bad result.
I guess I should use channels and then somehow cancel waiting for a channel. But how to do it exactly?
Full code:
package main
import (
"fmt"
"math/rand"
"time"
)
// random number between min and max
func random(min, max int) int {
rand.Seed(time.Now().Unix())
return rand.Intn(max-min) + min
}
// sleeps for a random milliseconds amount between 200 and 1000
func funcWithUnpredictiveExecutionTime() {
millisToSleep := random(200, 1000)
fmt.Println(fmt.Sprintf("Sleeping for %d milliseconds", millisToSleep))
time.Sleep(time.Millisecond * time.Duration(millisToSleep))
}
// measures execution time of a function funcWithUnpredictiveExecutionTime
// if expectedMs < actual execution time, it's ok.
// if expectedMs milliseconds passed and funcWithUnpredictiveExecutionTime
// still did not finish execution it should return
// without waiting for funcWithUnpredictiveExecutionTime
func measureTime(expectedMs float64) (ok bool) {
t1 := time.Now()
funcWithUnpredictiveExecutionTime()
t2 := time.Now()
diff := t2.Sub(t1)
actualMs := diff.Seconds() * 1000
ok = actualMs < expectedMs
fmt.Println(actualMs)
return
}
// prints results: Ok or too late
func printTimeResults(ok bool) {
if ok {
fmt.Println("Ok")
} else {
fmt.Println("Too late")
}
}
func main() {
printTimeResults(measureTime(200)) // expect it to finish in 200 ms anyway
printTimeResults(measureTime(1000)) // expect it to finish in 1000 ms anyway
}
Output:
Sleeping for 422 milliseconds
424.11895200000004
Too late
Sleeping for 422 milliseconds
425.27274900000003
Ok
Playground
You can't cancel a goroutine, unless you design it to be canceled. You can short circuit your timing function, by using a channel to signal the completion of the function being timed:
func measureTime(expectedMs float64) (ok bool) {
done := make(chan struct{})
t1 := time.Now()
go func() {
funcWithUnpredictiveExecutionTime()
close(done)
}()
select {
case <-done:
ok = true
case <-time.After(time.Duration(expectedMs) * time.Millisecond):
}
fmt.Println(time.Since(t1))
return ok
}
Extending JimB's example a little with the design I've personally followed for async background workers. I would say in most cases it's unacceptable to launch a go routine without passing an abort channel... All of your async methods should accept one as an argument or have one defined on their receiving type so you can actually control execution. fyi there are libraries for this, here's a simple one an old colleague of mine made; https://github.com/lytics/squaredance
If your program does not have an abort path for every goroutine you're probably going to face significant quality issues sooner or later. Also, for applications that are doing any heavy lifting in a goroutine, you will likely not be able to gracefully stop and start your application.
func measureTime(expectedMs float64) (ok bool) {
done := make(chan struct{})
abort := make(chan struct{})
t1 := time.Now()
go func() {
funcWithUnpredictiveExecutionTime(abort)
close(done)
}()
select {
case <-done:
ok = true
case <-time.After(time.Duration(expectedMs) * time.Millisecond):
// after signals here when the duration is reached so I close abort
close(abort)
}
fmt.Println(time.Since(t1))
return ok
}
funcWithUnpredictiveExecutionTime(abort) {
for {
select {
// doing work in here
case abort:
// except here, we clean up and return
}
}
}