What I found interesting is with this code run with raw on FreeBSD takes
~1s, however running via truss to see what happening with the syscalls
it takes only ~83ms e.g.
> ./tst
2018/04/03 21:53:28 Finished in 998.77123ms.
> truss -o t.txt ./tst
2018/04/03 21:53:31 Finished in 83.14988ms.
This only seems to effect really small duration's, time.Millisecond
isn't effected, which is perplexing.
On 03/04/2018 21:24, jake6...@gmail.com wrote:
For what it is worth, when I run your new code (without channels) on
windows it takes consistently 1 second. On Linux it takes variably
between 400ms and 1.5 seconds. Both running go 1.10. But, on my
systems, this seems to be actually measuring |time.Sleep()|. Removing
the call to |spin()| and the second |runtime.Gosched() |results in the
same times:
|
package main
import (
"log"
"runtime"
"time"
)
func main() {
runtime.GOMAXPROCS(1)
t0 := time.Now()
for i := 0; i < 1000; i++ {
time.Sleep(1 * time.Microsecond)
}
log.Printf("Finished in %v.", time.Since(t0))
}
|
I can not speak for your original example, but in this one I would be
looking to |time.Sleep()|.
- Jake
On Tuesday, April 3, 2018 at 2:12:40 PM UTC-4, brianbl...@gmail.com
wrote:
Hi Dave, thanks for the reply!
It makes sense that the send c <- 0 is not guaranteed to transfer
control to the receiving goroutine. But is it not guaranteed that
runtime.Gosched() will at least check if another goroutine is
runnable? I thought that was roughly the point of runtime.Gosched().
I see what you're saying in that when the second goroutine calls
Gosched, the sleep period may not be finished. But this will only
waste another 100 microseconds by design (not 100 milliseconds),
so it seems like control flow should return to the main goroutine
approximately when the sleep call finishes.
I created a simpler example, that doesn't use channels and avoids
the work length ambiguity, posted below. Now the secondary
goroutine just does an infinite loop of runtime.Gosched(). It
should be instantaneous to run (and is on my Mac), but it takes
almost exactly 5 seconds on Ubuntu, suggesting that there is some
fixed 5 millisecond delay on Gosched(). And adding a print above
spin's Gosched makes it instantaneous.
Thanks for your patience! I'm working on an application where the
~5ms Gosched delay is meaningful and I am very curious to figure
out what's going on here.
|
package main
import (
"log"
"runtime"
"time"
)
func spin() {
for {
runtime.Gosched()
}
}
func main() {
runtime.GOMAXPROCS(1)
go spin()
t0 := time.Now()
for i := 0; i < 1000; i++ {
time.Sleep(10 * time.Microsecond)
runtime.Gosched()
}
log.Printf("Finished in %v.", time.Since(t0))
}
|
On Tuesday, April 3, 2018 at 12:56:49 AM UTC-4,
brianbl...@gmail.com wrote:
I've run into some mysterious behavior, where Gosched() works
as expected in Mac OS X, but only works as expected in Ubuntu
if I put a logging statement before it.
I originally posted this on Stack Overflow but was directed
here. Post:
https://stackoverflow.com/questions/49617451/golang-scheduler-mystery-linux-vs-mac-os-x
<https://stackoverflow.com/questions/49617451/golang-scheduler-mystery-linux-vs-mac-os-x>
Any help would be greatly appreciated! Very curious what's
going on here, as this behavior came up while I was trying to
write a websocket broadcast server. Here's a minimal setup
that reproduces the behavior:
The main goroutine sleeps for 1000 periods of 1ms, and after
each sleep pushes a dummy message onto another goroutine via a
channel. The second goroutine listens for new messages, and
every time it gets one it does 10ms of work. So without any
|runtime.Gosched()| calls, the program will take 10 seconds to
run.
When I add periodic |runtime.Gosched()| calls in the second
goroutine, as expected the program runtime shrinks down to 1
second on my Mac. However, when I try running the same program
on Ubuntu, it still takes 10 seconds. I made sure to set
|runtime.GOMAXPROCS(1)| in both cases.
Here's where it gets really strange: if I just add a logging
statement before the the |runtime.Gosched()| calls, then
suddenly the program runs in the expected 1 second on Ubuntu
as well.
|packagemain import("time""log""runtime")func doWork(c chan
int){for{<-c // This outer loop will take ~10ms.forj :=0;j
<100;j++{// The following block of CPU work takes ~100
microsecondsfori :=0;i <300000;i++{_ =i *17}// Somehow this
print statement saves the day in
Ubuntulog.Printf("donkey")runtime.Gosched()}}}func
main(){runtime.GOMAXPROCS(1)c :=make(chan int,1000)go
doWork(c)start :=time.Now().UnixNano()fori :=0;i
<1000;i++{time.Sleep(1*time.Millisecond)// Queue up 10ms of
work in the other goroutine, which will backlog// this
goroutine without runtime.Gosched() calls.c <-0}// Whole
program should take about 1 second to run if the Gosched()
calls // work, otherwise 10 seconds.log.Printf("Finished in %f
seconds.",float64(time.Now().UnixNano()-start)/1e9)}|
||
--
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+unsubscr...@googlegroups.com
<mailto:golang-nuts+unsubscr...@googlegroups.com>.
For more options, visit https://groups.google.com/d/optout.
--
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.