[concurrency-interest] Spin Loop Hint support: Draft JEP proposal

Doug Lea dl at cs.oswego.edu
Sat Oct 24 14:09:44 EDT 2015


Here's one more attempt to explain why it would be a good idea
to place, name, and specify this method in a way that is more
general than "call this method only if you want a PAUSE instruction
on a dedicated multicore x86":

On 10/15/2015 01:23 PM, Gil Tene wrote:

> I also don't think that the "…momentarily unable to progress until the
> occurrence of one or more actions of one or more other threads. " is true:
> while (!(done || (count++ > threshold))) { spinLoopHint(); } can progress
> without any action by any other thread.

OK, this needs better wording to rule out silly interpretations
about loop bounds. See below.

>
> As noted in my proposed JavaDoc, I see the primary indication of the hint to
> be that the reaction time to events that would cause the loop to exit (e.g.
> in nanosecond units) is more important to the caller than the speed at which
> the loop is executing (e.g. in "number of loop iterations per second" units).

Sure. This can also be stated:

class Thread { ...
  /**
   * A hint to the platform that the current thread is momentarily
   * unable to progress until the occurrence of one or more actions of
   * one or more other threads (or that its containing loop is
   * otherwise terminated).  The method is mainly applicable in
   * spin-then-block constructions entailing a bounded number of
   * re-checks of a condition, separated by spinYield(), followed if
   * necessary with use of a blocking synchronization mechanism.  A
   * spin-loop that invokes this method on each iteration is likely to
   * be more responsive than it would otherwise be.
   */
   public static void spinYield();
}

> Anyone running indefinite spin loops on a uniprocessor deserves whatever they
> get. Yielding in order to help them out is not mercy. Let Darwin take care of
> them instead.
>
> But indefinite user-mode spinning on many-core systems is a valid and common
> use case (see the disruptor link in my previous e-mail).

> In such situations the spinning loop should just be calling yield(), or
> looping for a very short count (like your magic 64) and then yielding. A
> "magically choose for me whether reaction time or throughput or being nice to
> others is more important" call is not a useful hint IMO.
>
> Like in my uniprocessor comment above, any program spinning indefinitely (or
> for a non-trivial amount of time) with load > # cpus deserves what it gets.

The main problem here is that there are no APIs reporting whether
load > # cpus, and no good prospects for them either, especially
considering the use of hypervisors (that may intentionally mis-report)
and tightly packed cloud nodes where the number of cpus currently
available to a program may depend on random transient effects of
co-placement with other services running on that node.

And given that programmers cannot portably comply, the method must
allow implementations that take the best course of action known to the JVM.

Despite all of the above, I agree that an OK initial hotspot implementation
is just to emit PAUSE if on x86 else no-op. It might be worth then
experimenting with randomized branching etc on other platforms, and
someday further exploring some cheap form of load detection, perhaps
kicking in only upon repeated invocation.

-Doug




More information about the Concurrency-interest mailing list