[concurrency-interest] The code example in onSpinWait() Javadoc

Viktor Klang viktor.klang at gmail.com
Fri Nov 15 06:14:38 EST 2019


On Fri, 15 Nov 2019 at 12:38, Alex Otenko <oleksandr.otenko at gmail.com>
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, <
> concurrency-interest at cs.oswego.edu> 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 <
>> concurrency-interest at cs.oswego.edu> 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 <
>>> concurrency-interest at cs.oswego.edu> 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 <gil at azul.com> 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 <concurrency-interest at cs.oswego.edu> wrote:
>>>>> >
>>>>> > Gil Tene* Android typo error
>>>>> >
>>>>> > Il gio 14 nov 2019, 23:28 Francesco Nigro <nigro.fra at gmail.com> 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 <nigro.fra at gmail.com> 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 <oleksandr.otenko at gmail.com>
>>>>> 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,
>>>>> <concurrency-interest at cs.oswego.edu> 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 <
>>>>> nathanila at gmail.com> 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 <
>>>>> aph at redhat.com> 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
>>>>> > Concurrency-interest at cs.oswego.edu
>>>>> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>> > _______________________________________________
>>>>> > Concurrency-interest mailing list
>>>>> > Concurrency-interest at cs.oswego.edu
>>>>> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>>
>>>>> _______________________________________________
>>>> Concurrency-interest mailing list
>>>> Concurrency-interest at cs.oswego.edu
>>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>
>>> _______________________________________________
>>> Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>
>> --
>> Cheers,
>>>> _______________________________________________
>> Concurrency-interest mailing list
>> Concurrency-interest at cs.oswego.edu
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
> --
Cheers,
√
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20191115/5dc75007/attachment-0001.html>


More information about the Concurrency-interest mailing list