Only if it doesn't leave the shop like that, but with a P>0, it will. On Sat, 2018-03-17 at 15:24 -0700, matthewju...@gmail.com wrote: > Defending my reputation, I’m here for people making things, not for > being > an educator. Thinking quickly and making it work even with mistakes > can be > a valid approach sometimes. > > Matt > > On Saturday, March 17, 2018 at 2:05:55 PM UTC-5, Michael Jones wrote: > > > > > > these are excellent answers. > > > > i offer a harsher one:* the wrong answer faster is not > > optimization. *the > > law of programming has correctness at its core--imagine reasoning > > about a > > program where "if 5 < 7{stuff}" executed 50% of the time, or even > > 99.9999% > > of the time. if it was faster, that simply would not matter. this > > is what > > you cause then deny when you embrace race conditions of any kind, > > anywhere, > > ever. it means that your work only kind of works, in some cases, at > > some > > time, at the very best. > > > > it is the software equivalent of saying that cracked bridges have > > "not all > > that many cracks." don't go there. not just for your reputation, > > but for > > users and that of careful programmers. > > > > On Sat, Mar 17, 2018 at 9:40 AM, <thepud...@gmail.com > > <javascript:>> > > wrote: > > > > > > > > Hi all, > > > > > > In this particular case, this is a toy example of course, but for > > > this > > > toy example, it is absolutely a case where the performance of > > > the > > > synchronization primitive literally does not matter at all. (If I > > > followed > > > here, the intent is seemingly to watch a long running task, and > > > the example > > > has a 500ms sleep, etc.). > > > > > > That said, sometimes performance does matter. > > > > > > If instead this was a DIFFERENT example that was instead in some > > > tight > > > performance critical inner loop, the performance of the > > > synchronization > > > primitive for a stop flag can start to be meaningful (which of > > > course > > > should first be demonstrated by your benchmarking and/or your > > > profiling of > > > your particular program -- "premature optimization is the root of > > > all evil" > > > and all that). > > > > > > Empirically speaking, that is then a situation where I've seen > > > people > > > start to get into discussion around "well on amd64 you can rely > > > on X and Y > > > so we can get away with a stop flag that doesn't use a mutex or > > > an atomic", > > > and then people start talking about benign data races, and then > > > other > > > people start talking about "there are no benign data races", and > > > then > > > there's the reference to Dmitry Vyukov's article on benign data > > > races, etc.: > > > > > > > > > https://software.intel.com/en-us/blogs/2013/01/06/benign-data-rac > > > es-what-could-possibly-go-wrong > > > > > > To be honest I've seen it take up a fair amount of energy just > > > to > > > discuss, and again empirically speaking I've seen very smart > > > people make > > > mistakes here. > > > > > > One question I have regarding using an atomic for a stop flag is > > > whether > > > or not there is material performance overhead compared to a > > > simple > > > unprotected/non-atomic stop flag. > > > > > > I looked at that question a bit circa go ~1.7, so possibly stale > > > info > > > here, and I haven't gone back to look at my more detailed notes, > > > but if I > > > recall correctly I think my conclusion at the time was: > > > > > > 1. If your use case is a stop flag that will be checked many > > > times (say, > > > in a tight inner loop), and the stop flag only gets set rarely, > > > then the > > > performance of the set doesn't matter much, the assembly emitted > > > for an > > > atomic load (such as atomic.LoadUint64) seems to be identical for > > > the > > > assembly emitted for a simple load (say, *myUnint64Ptr) based on > > > some spot > > > checking a while ago (with a sample of assembly from 1.9 pasted > > > in at the > > > bottom of this post for comparison purposes). > > > > > > 2. Basic micro benchmarks didn't show a difference between an > > > atomic load > > > and an unprotected load for a stop flag. > > > > > > 3. There might be some theoretical possible overhead due to the > > > go > > > compiler will do instruction reordering in general, but won't do > > > instruction reordering across function calls, so that could be > > > one > > > difference that might or might not make a difference depending on > > > your > > > exact code (though likely modest impact)? Regarding this last > > > point, I'm > > > just an interested spectator when it comes to the go compiler, so > > > just to > > > be clear I don't really know this definitively. > > > > > > At least for us at the time, the quick test program & comparison > > > of > > > assembly was enough to move us past the whole "Well, on amd64 you > > > can get > > > away with X" discussion, so I didn't delve too much deeper than > > > that at the > > > time. > > > > > > In any event, sharing this sample assembly with the community in > > > case > > > anyone is interested and/or has additional commentary on the > > > particulars > > > here in terms of performance impact in go of using an atomic load > > > vs an > > > unprotected stop flag for the (admittedly somewhat rare) cases > > > when the > > > nanoseconds do indeed matter. (And for me, a clean report from > > > the race > > > detector trumps the performance arguments, but that doesn't mean > > > I'm not > > > curious about the performance...). > > > > > > Here is a simple test program: > > > > > > https://play.golang.org/p/PaCQwb5m9ag > > > > > > func simpleLoadUint64(inputPtr *uint64) uint64 { > > > // normal load of *inputPtr > > > return *inputPtr > > > } > > > > > > func atomicLoadUint64(inputPtr *uint64) uint64 { > > > // atomic.LoadUint64 atomically loads *inputPtr > > > return atomic.LoadUint64(inputPtr) > > > } > > > > > > And here is the corresponding assembly snippets (from go 1.9): > > > > > > go build -gcflags -S atomic_vs_normal_load.go > > > > > > // trivial function with an unprotected load > > > > > > "".simpleLoadUint64 STEXT nosplit size=14 args=0x10 locals=0x0 > > > 0x0000 00000 (atomic_vs_normal_load.go:8) TEXT > > > "".simpleLoadUint64(SB), NOSPLIT, $0-16 > > > 0x0000 00000 > > > (atomic_vs_normal_load.go:8) FUNCDATA $0, > > > gclocals·aef1f7ba6e2630c93a51843d99f5a28a(SB) > > > 0x0000 00000 > > > (atomic_vs_normal_load.go:8) FUNCDATA $1, > > > gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB) > > > 0x0000 00000 (atomic_vs_normal_load.go:8) MOVQ > > > "".inputPtr+8(SP), AX > > > 0x0005 00005 (atomic_vs_normal_load.go:10) MOVQ (AX), > > > AX > > > 0x0008 00008 (atomic_vs_normal_load.go:10) MOVQ AX, > > > "".~r1+16(SP) > > > 0x000d 00013 (atomic_vs_normal_load.go:10) RET > > > 0x0000 48 8b 44 24 08 48 8b 00 48 89 44 24 10 c3 > > > H.D$.H..H.D$.. > > > > > > // trivial function with a sync/atomic LoadUint64: > > > > > > "".atomicLoadUint64 STEXT nosplit size=14 args=0x10 locals=0x0 > > > 0x0000 00000 (atomic_vs_normal_load.go:13) TEXT > > > "".atomicLoadUint64(SB), NOSPLIT, $0-16 > > > 0x0000 00000 (atomic_vs_normal_load.go:13) > > > FUNCDATA $0, > > > gclocals·aef1f7ba6e2630c93a51843d99f5a28a(SB) > > > 0x0000 00000 (atomic_vs_normal_load.go:13) > > > FUNCDATA $1, > > > gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB) > > > 0x0000 00000 (atomic_vs_normal_load.go:13) MOVQ > > > "".inputPtr+8(SP), AX > > > 0x0005 00005 (atomic_vs_normal_load.go:15) MOVQ (AX), > > > AX > > > 0x0008 00008 (atomic_vs_normal_load.go:15) MOVQ AX, > > > "".~r1+16(SP) > > > 0x000d 00013 (atomic_vs_normal_load.go:15) RET > > > 0x0000 48 8b 44 24 08 48 8b 00 48 89 44 24 10 c3 > > > H.D$.H..H.D$.. > > > --thepudds > > > > > > On Saturday, March 17, 2018 at 10:37:48 AM UTC-4, matthe...@gmail > > > .com > > > wrote: > > > > > > > > > > > I think the second example alternative given (playground link > > > > above) has > > > > > > > > > > a data race? > > > > > > > > I’m not surprised that the race detector sees something (a read > > > > can > > > > happen during a write of the checked bool) but I don’t think > > > > this could > > > > actually cause problems because the var’s memory value will > > > > always be 0 or > > > > 1. > > > > > > > > There may be implementation details or future implementation > > > > details > > > > that cause a problem though, so one option could be to protect > > > > the bool as > > > > a shared resource with a mutex or equivalent, but I think rog’s > > > > solution is > > > > better anyway (the first one). > > > > > > > > They all involve either repeatedly checking on a timer or > > > > checking the > > > > > > > > > > value of another field (like polling) to see whether the long > > > > > running task > > > > > should be stopped. > > > > > > > > Right, now every iteration of the loop has more work added. > > > > > > > > Using os.Cmd may be an option, where you can call Kill on the > > > > separate > > > > process. > > > > > > > > Matt > > > > > > > > On Saturday, March 17, 2018 at 8:01:33 AM UTC-5, thepud...@gmai > > > > l.com > > > > wrote: > > > > > > > > > > > > > > > *> "Here's another way: https://play.golang.org/p/gEDef3LolAZ > > > > > > > > > > > > > > > > > <https://play.golang.org/p/gEDef3LolAZ> "* > > > > > > > > > > Hi all, > > > > > > > > > > I think the second example alternative given (playground link > > > > > above) > > > > > has a data race? > > > > > > > > > > Sample race detector run just now. (The two reports are > > > > > inverses of > > > > > each other: read then write vs. write then read). > > > > > > > > > > ----------------------------------------------------------- > > > > > ------------ > > > > > go run -race stop_flag_from_gonuts.go > > > > > > > > > > . . . . . quit sending ... > > > > > after quit sent================== > > > > > . > > > > > WARNING: DATA RACE > > > > > Write at 0x00c042072000 by goroutine 8: > > > > > main.f.func1() > > > > > C:/cygwin64/bin/gonuts/stop_flag_from_gonuts.go:13 > > > > > +0x59 > > > > > > > > > > Previous read at 0x00c042072000 by goroutine 6: > > > > > main.f() > > > > > C:/cygwin64/bin/gonuts/stop_flag_from_gonuts.go:17 > > > > > +0x102 > > > > > > > > > > Goroutine 8 (running) created at: > > > > > main.f() > > > > > C:/cygwin64/bin/gonuts/stop_flag_from_gonuts.go:11 > > > > > +0x8a > > > > > > > > > > Goroutine 6 (running) created at: > > > > > main.main() > > > > > C:/cygwin64/bin/gonuts/stop_flag_from_gonuts.go:28 > > > > > +0x70 > > > > > ================== > > > > > ================== > > > > > WARNING: DATA RACE > > > > > Read at 0x00c042072000 by goroutine 6: > > > > > main.f() > > > > > C:/cygwin64/bin/gonuts/stop_flag_from_gonuts.go:17 > > > > > +0x102 > > > > > > > > > > Previous write at 0x00c042072000 by goroutine 8: > > > > > main.f.func1() > > > > > C:/cygwin64/bin/gonuts/stop_flag_from_gonuts.go:13 > > > > > +0x59 > > > > > > > > > > Goroutine 6 (running) created at: > > > > > main.main() > > > > > C:/cygwin64/bin/gonuts/stop_flag_from_gonuts.go:28 > > > > > +0x70 > > > > > > > > > > Goroutine 8 (finished) created at: > > > > > main.f() > > > > > C:/cygwin64/bin/gonuts/stop_flag_from_gonuts.go:11 > > > > > +0x8a > > > > > ================== > > > > > quit called > > > > > Found 2 data race(s) > > > > > exit status 66 > > > > > ----------------------------------------------------------- > > > > > ------------ > > > > > > > > > > --thepudds > > > > > > > > > > On Friday, March 16, 2018 at 11:04:38 AM UTC-4, matthe...@gma > > > > > il.com > > > > > wrote: > > > > > > > > > > > > > > > > > > While this is running, your select won't be receiving on > > > > > > the quit > > > > > > > > > > > > > > channel, even if it is non-nil. > > > > > > > If you want to be able to cancel it, you'll need to make > > > > > > > the code in > > > > > > > the loop responsive to the quit channel > > > > > > > (for example, by using a select like you're using in f > > > > > > > already). > > > > > > > > > > > > The default select case does it: https://play.golang.org/p/ > > > > > > jlfaXu6TZ8L > > > > > > > > > > > > Here's another way: https://play.golang.org/p/gEDef3LolAZ > > > > > > > > > > > > Matt > > > > > > > > > > > > On Friday, March 16, 2018 at 9:45:00 AM UTC-5, Sathish VJ > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > All the examples I've seen use some kind of ticker to run > > > > > > > various > > > > > > > cases of a select statement. But how does one run a long > > > > > > > running task that > > > > > > > is still cancelable? > > > > > > > > > > > > > > > > > > > > > In the example below the quit part is never reached. > > > > > > > > > > > > > > https://play.golang.org/p/PLGwrUvKaqn (it does not run > > > > > > > properly on > > > > > > > play.golang.org). > > > > > > > > > > > > > > package main > > > > > > > > > > > > > > > > > > > > > import ( > > > > > > > "fmt" > > > > > > > "os" > > > > > > > "time" > > > > > > > ) > > > > > > > > > > > > > > > > > > > > > func f(quit chan bool) { > > > > > > > for { > > > > > > > select { > > > > > > > case <-time.After(0 * time.Second): > > > > > > > // start long running task immediately. > > > > > > > for { > > > > > > > time.Sleep(500 * time.Millisecond) > > > > > > > fmt.Printf(". ") > > > > > > > } > > > > > > > case <-quit: > > > > > > > fmt.Println("quit called") > > > > > > > //deallocate resources in other long running task > > > > > > > and then > > > > > > > return from function. > > > > > > > os.Exit(0) // or return > > > > > > > } > > > > > > > } > > > > > > > } > > > > > > > > > > > > > > > > > > > > > func main() { > > > > > > > var quit chan bool > > > > > > > go f(quit) > > > > > > > > > > > > > > > > > > > > > println("quit sending ... ") > > > > > > > quit <- true > > > > > > > println("after quit sent") > > > > > > > > > > > > > > > > > > > > > var i chan int > > > > > > > <-i > > > > > > > } > > > > > > > > > > > > > > > > > > > > > -- > > > 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 <javascript:>. > > > For more options, visit https://groups.google.com/d/optout. > > > > > > > > > -- > > Michael T. Jones > > michae...@gmail.com <javascript:> > >
-- 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.