Agreed. Copy-on-write is also very good if the shared structure is small. > On Feb 4, 2023, at 1:00 PM, Kurtis Rader <kra...@skepticism.us> wrote: > > > FWIW, Using an RCU (https://en.wikipedia.org/wiki/Read-copy-update) algorithm > is often the best choice for caches where reads happen several orders of > magnitude more often than writes. RCU usually avoids the need for any mutex > by readers. I was working at Sequent Computer Systems when this was > implemented for the network ARP and routing tables and was friends with the > engineers who designed and patented RCU. I remember reading their patent and > looking at the kernel implementation and thinking to myself how brilliant the > concept was. > >> On Sat, Feb 4, 2023 at 8:49 AM robert engels <reng...@ix.netcom.com> wrote: >> I took some time to put this to a test. The Go program here >> https://go.dev/play/p/378Zn_ZQNaz uses a VERY short holding of the lock - >> but a large % of runtime holding the lock. >> >> (You can’t run it on the Playground because of the length of time). You can >> comment/uncomment the lines 28-31 to test the different mutexes, >> >> It simulates a common system scenario (most web services) - lots of readers >> of the cache, but the cache is updated infrequently. >> >> On my machine the RWMutex is > 50% faster - taking 22 seconds vs 47 seconds >> using a simple Mutex. >> >> It is easy to understand why - you get no parallelization of the readers >> when using a simple Mutex. >> >>> On Jan 30, 2023, at 8:29 PM, Ian Lance Taylor <i...@golang.org> wrote: >>> >>>> On Mon, Jan 30, 2023 at 4:42 PM Robert Engels <reng...@ix.netcom.com> >>>> wrote: >>>> >>>> Yes but only for a single reader - any concurrent reader is going to >>>> park/deschedule. >>> >>> If we are talking specifically about Go, then it's more complex than >>> that. In particular, the code will spin briefly trying to acquire the >>> mutex, before queuing. >>> >>>> There’s a reason RW locks exist - and I think it is pretty common - but >>>> agree to disagree :) >>> >>> Sure: read-write locks are fine and appropriate when the program holds >>> the read lock for a reasonably lengthy time. As I said, my analysis >>> only applies when code holds the read lock briefly, as is often the >>> case for a cache. >>> >>> Ian >>> >>> >>>>> On Jan 30, 2023, at 6:23 PM, Ian Lance Taylor <i...@golang.org> wrote: >>>>> >>>>> On Mon, Jan 30, 2023 at 1:00 PM Robert Engels <reng...@ix.netcom.com> >>>>> wrote: >>>>>> >>>>>> Pure readers do not need any mutex on the fast path. It is an atomic CAS >>>>>> - which is faster than a mutex as it allows concurrent readers. On the >>>>>> slow path - fairness with a waiting or active writer - it degenerates in >>>>>> performance to a simple mutex. >>>>>> >>>>>> The issue with a mutex is that you need to acquire it whether reading or >>>>>> writing - this is slow…. (at least compared to an atomic cas) >>>>> >>>>> The fast path of a mutex is also an atomic CAS. >>>>> >>>>> Ian >>>>> >>>>>>>> On Jan 30, 2023, at 2:24 PM, Ian Lance Taylor <i...@golang.org> wrote: >>>>>>> >>>>>>> On Mon, Jan 30, 2023 at 11:26 AM Robert Engels <reng...@ix.netcom.com> >>>>>>> wrote: >>>>>>>> >>>>>>>> I don’t think that is true. A RW lock is always better when the reader >>>>>>>> activity is far greater than the writer - simply because in a good >>>>>>>> implementation the read lock can be acquired without >>>>>>>> blocking/scheduling activity. >>>>>>> >>>>>>> The best read lock implementation is not going to be better than the >>>>>>> best plain mutex implementation. And with current technology any >>>>>>> implementation is going to require atomic memory operations which >>>>>>> require coordinating cache lines between CPUs. If your reader >>>>>>> activity is so large that you get significant contention on a plain >>>>>>> mutex (recalling that we are assuming the case where the operations >>>>>>> under the read lock are quick) then you are also going to get >>>>>>> significant contention on a read lock. The effect is that the read >>>>>>> lock isn't going to be faster anyhow in practice, and your program >>>>>>> should probably be using a different approach. >>>>>>> >>>>>>> Ian >>>>>>> >>>>>>>>>> On Jan 30, 2023, at 12:49 PM, Ian Lance Taylor <i...@golang.org> >>>>>>>>>> wrote: >>>>>>>>> >>>>>>>>> On Sun, Jan 29, 2023 at 6:34 PM Diego Augusto Molina >>>>>>>>> <diegoaugustomol...@gmail.com> wrote: >>>>>>>>>> >>>>>>>>>> From times to times I write a scraper or some other tool that would >>>>>>>>>> authenticate to a service and then use the auth result to do stuff >>>>>>>>>> concurrently. But when auth expires, I need to synchronize all my >>>>>>>>>> goroutines and have a single one do the re-auth process, check the >>>>>>>>>> status, etc. and then arrange for all goroutines to go back to work >>>>>>>>>> using the new auth result. >>>>>>>>>> >>>>>>>>>> To generalize the problem: multiple goroutines read a cached value >>>>>>>>>> that expires at some point. When it does, they all should block and >>>>>>>>>> some I/O operation has to be performed by a single goroutine to >>>>>>>>>> renew the cached value, then unblock all other goroutines and have >>>>>>>>>> them use the new value. >>>>>>>>>> >>>>>>>>>> I solved this in the past in a number of ways: having a single >>>>>>>>>> goroutine that handles the cache by asking it for the value through >>>>>>>>>> a channel, using sync.Cond (which btw every time I decide to use I >>>>>>>>>> need to carefully re-read its docs and do lots of tests because I >>>>>>>>>> never get it right at first). But what I came to do lately is to >>>>>>>>>> implement an upgradable lock and have every goroutine do: >>>>>>>>> >>>>>>>>> >>>>>>>>> We have historically rejected this kind of adjustable lock. There is >>>>>>>>> some previous discussion at https://go.dev/issue/4026, >>>>>>>>> https://go.dev/issue/23513, https://go.dev/issue/38891, >>>>>>>>> https://go.dev/issue/44049. >>>>>>>>> >>>>>>>>> For a cache where checking that the cached value is valid (not stale) >>>>>>>>> and fetching the cached value is quick, then in general you will be >>>>>>>>> better off using a plain Mutex rather than RWMutex. RWMutex is more >>>>>>>>> complicated and therefore slower. It's only useful to use an RWMutex >>>>>>>>> when the read case is both contested and relatively slow. If the read >>>>>>>>> case is fast then the simpler Mutex will tend to be faster. And then >>>>>>>>> you don't have to worry about upgrading the lock. >>>>>>>>> >>>>>>>>> Ian >>>>>>>>> >>>>>>>>> -- >>>>>>>>> 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. >>>>>>>>> To view this discussion on the web visit >>>>>>>>> https://groups.google.com/d/msgid/golang-nuts/CAOyqgcXNVFkc5H-L6K4Mt81gB6u91Ja07hob%3DS8Qwgy2buiQjQ%40mail.gmail.com. >>>>>>> >>>>>>> -- >>>>>>> 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. >>>>>>> To view this discussion on the web visit >>>>>>> https://groups.google.com/d/msgid/golang-nuts/CAOyqgcWJ%2BLPOoTk9H7bxAj8_dLsuhgOpy_bZZrGW%3D%2Bz6N%3DrX-w%40mail.gmail.com. >>>>> >>>>> -- >>>>> 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. >>>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/golang-nuts/CAOyqgcVLzkTgiYqw%2BWh6pTFX74X-LYoyPFK5bkX7T8J8j3mb%3Dg%40mail.gmail.com. >> >> -- >> 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. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/2AA31B8D-8A35-4894-AC1F-48E830297887%40ix.netcom.com. > > > -- > Kurtis Rader > Caretaker of the exceptional canines Junior and Hank > -- > 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. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/CABx2%3DD9TQ_b_Bu1yAsksO%3DjUFzziHdhbCTnBvRsn_5jW8cuwfA%40mail.gmail.com.
-- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/E04571D6-9E84-4C08-83B3-52B14BFA4FA7%40ix.netcom.com.