Re: The code example in onSpinWait() Javadoc
Viktor Klang via Concurrency-interest <[email protected]>
| Newsgroups | gmane.comp.java.jsr.166-concurrency |
|---|---|
| Message-ID | <CANPzfU-C=7-VdheMybvoy3YOMv_Qz=2O484SQFKjEYxsx-QURQ@mail.gmail.com> |
On Fri, 15 Nov 2019 at 12:38, Alex Otenko <[email protected]> wrote: > Let's start with why you wouldn't just park nanos. Because you want the > CPU to do something useful instead of idling. > I hope you trust that I know this. :-) > For a time limit to be implementable for arbitrary useful things, the > computation done by onSpinWait must know how much time that computation > will take - maybe to choose the computation of the right size. Gödel says > hello > Are you arguing for the removal of all polling-style API:s in Java? . > > Or you should be able to suspend that computation at arbitrary points. > Well, not in Java. > That’d be nice, but yeah, not really until Fibers. But something crucial to factor in is wakeup delay. > Alex > > On Fri, 15 Nov 2019, 10:25 Viktor Klang via Concurrency-interest, < > [email protected]> wrote: > >> It would be interesting to have an onSpinWait(long nanos) version ehich >> can be intrinsified if need be to provide the most accurate delay based on >> the underlying system. >> >> Talking about time being meaningless in a non-RT OS is rather meaningless >> in itself—we’re relying on getting CPU timeslices before the end of the >> universe anyway ;) >> >> On Fri, 15 Nov 2019 at 12:06, Roman Leventov via Concurrency-interest < >> [email protected]> wrote: >> >>> By "half-baked" I meant specifically that the example could be valid but >>> only under specific conditions, such as core-pinned thread, or backoff >>> timeout event, etc. However, the "mundane" class and method names which are >>> chosen ("EventHandler") may mislead users into thinking that spin-loop is a >>> good go-to strategy to waiting for some conditions/logic executed, instead >>> of using a synchronization primitive or attaching a listener to a >>> CompletableFuture/ListeanableFuture if one is involved. >>> >>> I like Francesco's example because it is self-contained and doesn't need >>> any backoff, so the complicated discussion of the tradeoffs involved and >>> conditions which should be accounted for (typical wait time, GC algorithm, >>> busyness of the system, etc.) could be blissfully omitted. >>> >>> On Fri, 15 Nov 2019 at 11:05, Francesco Nigro via Concurrency-interest < >>> [email protected]> wrote: >>> >>>> Hi Gil, >>>> >>>> It's one of the common use cases >>>> >>>> :) Although I can say the same I'm not quite sure that is that common >>>> and your example re LMAX makes it even more clear (not that mine on JCTools >>>> is better eh!) >>>> On the other hand, onSpinWait itself is equally uncommon on j.u.c., so >>>> I take all your points re the existing doc. >>>> >>>> Would a more detailed/complicated/opinionated example of a specific >>>>> backoff flavor would help >>>>> make the meaning and use of the method more clear, or help point out >>>>> caveats or pitfalls better? >>>> >>>> My (personal) fear is that users will recognize the general busy spin >>>> loop pattern, thinking that given that the JVM "is able to optmize it" >>>> (thanks to help of unicorns and rainbows too) and >>>> making it a much more attractive pairs of scissors to play with then >>>> before :) >>>> >>>> >>>> Il giorno ven 15 nov 2019 alle ore 06:38 Gil Tene <[email protected]> ha >>>> scritto: >>>> >>>>> I guess I'm missing something about the starting point in this thread. >>>>> What do you find "half baked" >>>>> about the actual example in the Javadoc? It's one of the common use >>>>> cases (with no time-based >>>>> backoffs) in various applications (ones that e.g. dedicate a spinning >>>>> thread on a dedicated core). >>>>> >>>>> E.g. >>>>> https://github.com/LMAX-Exchange/disruptor/blob/5764f3b01faab603322c61cede957b7e79f58c8b/src/main/java/com/lmax/disruptor/BusySpinWaitStrategy.java >>>>> >>>>> There are obviously additional common variants, some of which include >>>>> backoff mechanisms >>>>> (time based, count based, phase of moon based, etc.), but IMO there is >>>>> no "right way" to do this, >>>>> and a no-backoff use case is just as valid (and maybe even common) as >>>>> one that includes a >>>>> backoff. The code carefully avoids spelling out how >>>>> "eventNotificationNotReceived" is determined. >>>>> Hey, the event may even be a backoff timeout... >>>>> >>>>> Would a more detailed/complicated/opinionated example of a specific >>>>> backoff flavor would help >>>>> make the meaning and use of the method more clear, or help point out >>>>> caveats or pitfalls better? >>>>> >>>>> > On Nov 14, 2019, at 2:28 PM, Francesco Nigro via >>>>> Concurrency-interest <[email protected]> wrote: >>>>> > >>>>> > Gil Tene* Android typo error >>>>> > >>>>> > Il gio 14 nov 2019, 23:28 Francesco Nigro <[email protected]> ha >>>>> scritto: >>>>> > I would like to hear the opinion of Gil Gene about it too: AFAIK he >>>>> was the one (or one of many?) that has proposed it to be included in >>>>> http://openjdk.java.net/jeps/285 >>>>> > >>>>> > Il gio 14 nov 2019, 23:22 Francesco Nigro <[email protected]> ha >>>>> scritto: >>>>> > Beside being more complex? >>>>> > Not much I admit :) >>>>> > But IMO awaiting with no algorithmical indication of the duration of >>>>> the wait (like in the javadoc) and awaiting for a finite amount of "time" a >>>>> condition that will be true at some point, is a better example where to >>>>> apply onSpinWait, although is not technically incorrect to use it for >>>>> "blind" spin loop as well. >>>>> > Maybe is just a subtle difference, but I won't encourage users to >>>>> blindly spin loop on conditions and just use onSpinWait to save the day.. >>>>> probably I'm worried too much for something very simple and unavoidable; as >>>>> @roman has suggested, probably no example is better then one that is a >>>>> superclass of all the possible best cases. >>>>> > >>>>> > >>>>> > Il gio 14 nov 2019, 22:51 Alex Otenko <[email protected]> >>>>> ha scritto: >>>>> > What's the difference between this example and what's in javadocs? >>>>> > >>>>> > Alex >>>>> > >>>>> > On Thu, 14 Nov 2019, 16:29 Francesco Nigro via Concurrency-interest, >>>>> <[email protected]> wrote: >>>>> > Totally right, sorry again (writing by phone is a terrible idea :( ): >>>>> > yes , poll should use "o = this.obj". >>>>> > >>>>> > > Can we get rid of "done"? Since offerOnce() does not allow null, >>>>> then having the done flag does not seem to help anything. >>>>> > Absolutely yes: I've prepared this as a "simplified" (and wrong due >>>>> to the hurry, sorry for that) version of what we do on many queues in >>>>> JCtools, >>>>> > that's why it contains some unnecessary bits as you've rightly >>>>> pointed out. >>>>> > Code that is spin awaiting on a condition, sure that it will happen >>>>> at some point in the future, is something that could help to understand the >>>>> rare cases >>>>> > where using onSpinWait could be beneficial IMO. >>>>> > >>>>> > >>>>> > >>>>> > Il giorno gio 14 nov 2019 alle ore 17:18 Nathan and Ila Reynolds < >>>>> [email protected]> ha scritto: >>>>> > In poll(), should "this.obj = o" be "o = this.obj"? Without this >>>>> change, it seems poll() could spin forever. >>>>> > >>>>> > Should "poll" be renamed to "take" since the method could block >>>>> until a value is available? >>>>> > >>>>> > Can we get rid of "done"? Since offerOnce() does not allow null, >>>>> then having the done flag does not seem to help anything. >>>>> > >>>>> > Is the compiler and execution engine in my head misinterpreting and >>>>> mis-executing the code? >>>>> > >>>>> > Here is the code with my suggested changes. >>>>> > >>>>> > volatile E obj = null; >>>>> > >>>>> > public void offerOnce(E o) { >>>>> > Objects.checkNonNull(o); >>>>> > this.obj = o; >>>>> > } >>>>> > >>>>> > public boolean isDone() { >>>>> > return obj != null; >>>>> > } >>>>> > >>>>> > public E take() { >>>>> > E o; >>>>> > >>>>> > while (true) { >>>>> > o = obj; >>>>> > >>>>> > if (o != null) >>>>> > return o; >>>>> > >>>>> > java.lang.Thread.onSpinWait(); >>>>> > } >>>>> > } >>>>> > -Nathan >>>>> > On 11/14/2019 8:54 AM, Francesco Nigro wrote: >>>>> >> Sorry I've written on the email text, I forgot an important part, >>>>> let me write it properly: >>>>> >> >>>>> >> volatile E obj = null; >>>>> >> volatile boolean done = false; >>>>> >> >>>>> >> public void offerOnce(E o) { >>>>> >> Objects.checkNonNull(o); >>>>> >> this.done = true; >>>>> >> this.obj = o; >>>>> >> } >>>>> >> >>>>> >> public boolean isDone() { >>>>> >> return done; >>>>> >> } >>>>> >> >>>>> >> public E poll() { >>>>> >> E o = this.obj; >>>>> >> if (o == null && !this.done) { >>>>> >> return null; >>>>> >> } >>>>> >> //o will be !null at some point >>>>> >> do { >>>>> >> if (o != null) >>>>> >> return o; >>>>> >> java.lang.Thread.onSpinWait(); >>>>> >> this.obj = o; >>>>> >> } while(true); >>>>> >> } >>>>> >> >>>>> >> Similarly to the queue API: poll should return null iff !done, but >>>>> offer update first done and then this.obj: >>>>> >> poll need to read obj, but has to stay consistent to the ordering, >>>>> so at some point, obj will be visible if done == true. >>>>> >> On JCtools we have some queues with a similar behaviour (producer >>>>> sequence is advanced before writing the actual element in the queue) >>>>> >> and we need to spin wait the element apprearence to stay consistent >>>>> with the isEmpty behaviour: that's a good use case for onSpinWait (when it >>>>> works :P). >>>>> >> >>>>> >> >>>>> >> >>>>> >> Il giorno gio 14 nov 2019 alle ore 16:43 Andrew Haley < >>>>> [email protected]> ha scritto: >>>>> >> On 11/14/19 3:31 PM, Francesco Nigro via Concurrency-interest wrote: >>>>> >> > E o = this.obj; >>>>> >> > if (o == null && !done) { >>>>> >> > return null; >>>>> >> > } >>>>> >> > //o will be !null at some point >>>>> >> > do { >>>>> >> > if (o != null) >>>>> >> > return o; >>>>> >> > java.lang.Thread.onSpinWait(); >>>>> >> > } while(true); >>>>> >> > } >>>>> >> > >>>>> >> > In case like this is more appropriate, maybe, but much less >>>>> intuitive >>>>> >> > probably. >>>>> >> >>>>> >> Umm, what? o is a local. This loop spins forever. >>>>> >> >>>>> >> -- >>>>> >> Andrew Haley (he/him) >>>>> >> Java Platform Lead Engineer >>>>> >> Red Hat UK Ltd. <https://www.redhat.com> >>>>> >> https://keybase.io/andrewhaley >>>>> >> EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671 >>>>> >> >>>>> > _______________________________________________ >>>>> > Concurrency-interest mailing list >>>>> > [email protected] >>>>> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest >>>>> > _______________________________________________ >>>>> > Concurrency-interest mailing list >>>>> > [email protected] >>>>> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest >>>>> >>>>> _______________________________________________ >>>> Concurrency-interest mailing list >>>> [email protected] >>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest >>>> >>> _______________________________________________ >>> Concurrency-interest mailing list >>> [email protected] >>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest >>> >> -- >> Cheers, >> √ >> _______________________________________________ >> Concurrency-interest mailing list >> [email protected] >> http://cs.oswego.edu/mailman/listinfo/concurrency-interest >> > -- Cheers, √ _______________________________________________ Concurrency-interest mailing list [email protected] http://cs.oswego.edu/mailman/listinfo/concurrency-interest