Pls review 7091418: FX priority class from Solaris should be available to JVM )

Paul Hohensee paul.hohensee at
Tue Jan 24 12:16:27 PST 2012

I've filed

7132966: Allow mapping of Java thread priorities to OS scheduling classes as
                 well as priorities

to track your recommendation.


On 1/24/12 2:55 PM, Paul Hohensee wrote:
> Thanks for the review.
> Inline...
> On 1/23/12 11:53 PM, David Holmes wrote:
>> Hi Paul,
>> Warning: long winded response below
> Looking forward to it. :)
>> Summary:
>> - file RFE to fully support "system" priority for VM internal threads
>> - Fully implement UseCriticalJavaThreadPriority on non-Solaris
>> You'll have to read on to understand what I mean by both of these :)
>> On 24/01/2012 8:00 AM, Paul Hohensee wrote:
>>> I just found
>>> 7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60
>>> on Solaris 10 and 11
>>> which seems like the CR I should actually be using.
>>> Ref your last comment on 7082553, we could indeed change the definition
>>> of JavaPriority10_To_OSPriority, but that would cover only Java 
>>> threads,
>>> not compiler or the CMS background threads.
>> Thanks for reminding me about this CR - I knew there had been further 
>> discussion on this. That CR is not public, which seems a little 
>> pointless now.
> Yes.  I've made 7082553 public and make 7091418 a dup of 7082553.
>> I'll restate my concerns as outlined in that CR. It is very difficult 
>> for an application programmer to determine that FX60 will provide any 
>> performance benefit, whether assigned to a compiler thread, GC thread 
>> or Java thread. The benefits of FX60 only exist when a system has 
>> idle cores, so the application programmer and/or the application 
>> "deployer" has to know what overall load will exist on the system. 
>> For the GC and compiler threads this is not such an issue as the 
>> person deploying the app can simply experiment with the flag being on 
>> and off and see it it helps in their situation.
> Undoubtedly true that only experts should be using it.  There are 
> significant
> Oracle applications running on T4 that contain serial bottlenecks, so 
> by definition
> there are idle cores available.
>> For Java threads however the application programmer has to use 
>> Thread.MAX_PRIORITY. This has two negative consequences. First it 
>> encourages people to start thinking about Thread priorities when we 
>> have spent a dozen years telling them to forget about them because in 
>> 99% of the cases they have no meaning. For them to have meaning you 
>> have to select non default ThreadPriorityPolicy settings and use the 
>> right OS - even then you get different affects on different OSes. 
>> Which leads me to the second consequence: a loss of portability. 
>> Using Thread.MAX_PRIORITY can have different consequences on 
>> different platforms, even today.
> That's true.  Imo, the correct solution is to invent a QOS API at a 
> higher abstraction
> level, e.g., something like Thread.prefer(SYSTEM_THROUGHPUT) or
> Thread.prefer(FAST_RESPONSE_TIME).  We wanted to get something useful 
> sooner
> than that though, hence this RFE.  Note that it's very much 
> experimental, which
> is why it's use is gated by -XX:+UseExperimentalVMOptions.  There's no
> guarantee at all that we'll continue to support these switches.
>> Ok - so the response to the above is "These are experimental options 
>> which must be unlocked, and its for advanced users and 'caveat 
>> emptor'". I can live with that, so lets look at the details of the 
>> implementation.
> Ah, didn't need to write the above. :)
>> There are really two distinct parts to this. First the ability to 
>> define a special system thread priority. In that regard I like the 
>> idea of creating a pseudo-priority of 11 and using that to map to 
>> this system, aka critical, priority (though this could be better 
>> documented). You then have flags the say "use the system priority for 
>> threads of type X". This is cross-platform. There are two things I 
>> find problematic with this though:
>> 1. As priority is simply a number we can't directly use this to 
>> implement FX60. Instead we have to put in a hack where a negative 
>> value on Solaris tells the system specific code "that means FX 60".
> Yes.  I could make things a little better by having a negative number 
> mean
> "FX" and to use the positive equivalent directly (i.e., not scale 
> it).  An alternative
> would be to add a second mapping array (or make an array of structs) that
> contains the desired scheduling class.  This seemed like overkill to me
> given the limited goal of this change.
>> 2. There is no mechanism, apart from recompiling the VM, to actually 
>> control what this system/critical priority is.
> True.
>> So this general purpose mechanism falls somewhat short of being 
>> generally useful as a cross-platform mechanism. I find both of these 
>> unsatisfactory and a RFE should be filed to address them.
> It's intended to be Solaris-only right now, which is why I didn't 
> implement the
> full-blown solution on non-Solaris platforms.  Rather I made it 
> incidental to
> an understandable Solaris implementation, esp. the common code parts
> in compileBroker.cpp and concurrentMarkSweepThread.cpp.
> I'll file an RFE along the lines of being able to specify a scheduling 
> class
> and priority for each Java thread priority.  Either extend 
> JavaPriority<n>_To_OSPriority
> to take a CSV list argument (which is coming to the command line 
> parser at
> some point anyway), or add 10 more switches to specify the scheduling 
> class.
>> The second part is the "map Thread.MAX_PRIORITY to the critical 
>> priority" part. On Solaris you use UseCriticalJavaThreadPriority to 
>> actually update the priority mapping 10 -> critical. But you don't do 
>> this on the other platforms. This is what I object to - if you are 
>> going to make this a cross-platform setting then it should be 
>> implemented fully on all platforms. It doesn't matter that by default 
>> the end result is the same, the code should be there so that if you 
>> could define the critical priority at runtime things would work as 
>> expected.
> I didn't do it on non-Solaris platforms (at least not in the code) 
> because on those
> platforms CriticalPriority is the same as MaxPriority.  No runtime 
> mapping needed.
> For compiler threads and the CMS background thread on non-Solaris 
> platforms,
> using critical priority will up their priority, which is new.
> I don't know what other equivalent (i.e., scheduling classes) to use 
> on non-Solaris
> platforms.  Can you recommend something so I can put it in an RFE?  I 
> hesitate to
> do more than I have because we're at the end of the development cycle 
> for 7u4/hs23.
> Paul
>> Cheers,
>> David
>> -----
>>> Paul
>>> On 1/23/12 2:11 PM, Paul Hohensee wrote:
>>>> Thanks for the review.
>>>> Inline...
>>>> On 1/22/12 7:39 PM, David Holmes wrote:
>>>>> Hi Paul,
>>>>> The meta-comment here is that there needs to be a clear description
>>>>> of what "critical priority" means and what constraints there are on
>>>>> setting it to some OS specific value. For example the current changes
>>>>> uses the FX scheduling class, but what if someone used the RT
>>>>> scheduling class instead? Would that work? Probably not, in which
>>>>> case we should document that this selection of the "critical
>>>>> priority" is not an arbitrary choice that can be made.
>>>>> Even for FX/60 I'm not certain that using this for Java threads might
>>>>> not prevent safepoints from being reached or induce some other form
>>>>> of livelock.
>>>> I added material to the Comments field of the CR.
>>>> I don't think there's a livelock problem with Java threads, because
>>>> Solaris takes
>>>> FX60 as advisory, not as a command. All that should happen is that a
>>>> critical
>>>> priority Java thread will get to the safepoint earlier than
>>>> non-critical ones.
>>>> I suppose it's possible for critical priority CMS or compiler threads
>>>> to starve
>>>> non-critical Java threads, but they run at NearMaxPriority by default
>>>> now,
>>>> which can do the same thing. This is definitely an "expert-only" 
>>>> feature
>>>> though, which is why it's experimental for the time being.
>>>>> On 21/01/2012 3:13 AM, Paul Hohensee wrote:
>>>>>> Webrev here
>>>>>> This change defines a new Java pseudo-priority called
>>>>>> CriticalPriority, just above MaxPriority. Compiler threads, the CMS
>>>>>> background thread, and Java threads can have the os equivalent of
>>>>>> this priority. On Solaris, this is the FX/60 scheduling
>>>>>> class/priority. On other platforms, it's the same as 
>>>>>> MaxPriority's os
>>>>>> priority.
>>>>> For reference this is why the mapping to FX/60 has been proposed:
>>>>> I still don't fully grok what this optimization does in a general
>>>>> sense and it seems to be geared to providing better single-threaded
>>>>> performance on near-idle systems - which doesn't make any sense to me
>>>>> in a JVM context. But FX/60 also gives you true priority over TS/IA
>>>>> threads so that may be where the gain comes from. I wonder if any
>>>>> experiments were actually done using FX/59 rather than the "magical"
>>>>> FX/60?
>>>> It's meant to be Solaris-Sparc-specific, but it was easier to
>>>> implement as a
>>>> general feature than to specialize it. Given enough cores, FX60 does
>>>> indeed
>>>> give you true priority over TS/IA threads. If there aren't enough 
>>>> cores
>>>> to run both critical threads in single-thread mode and non-critical
>>>> threads
>>>> at the same time, Solaris will allow non-critical threads to run on 
>>>> the
>>>> same core(s) as critical ones.
>>>> I don't know of any FX59 experiments, but given the amount of work
>>>> it's taken
>>>> for the Solaris folks to get FX60 working, I doubt using it would have
>>>> any positive
>>>> effect.
>>>>>> There are 3 new command line switches, all gated by
>>>>>> UseExperimentalVMOptions.
>>>>>> -XX:+UseCriticalJavaThreadPriority
>>>>>> Maps Java MAX_PRIORITY to critical priority.
>>>>> I found what you have done here to be very confusing. The only place
>>>>> UseCriticalJavaThreadPriority is used is on Solaris. There you re-map
>>>>> the priority mapping for priority 10 to the "critical priority" as
>>>>> described.
>>>> It's actually used on the other OSs. It just maps to MaxPriority on
>>>> those.
>>>>> On all platforms you added an entry to the priority mapping table(s)
>>>>> for a non-existent Java priority 11. This provides a way to lookup
>>>>> the "critical priority" for the CMS/Compiler threads - in essence use
>>>>> of critical priority for those threads says "pretend these have Java
>>>>> priority 11" and then you've added a mapping for a priority 11 that
>>>>> is the same as for priority 10 except on Solaris. On Solaris you had
>>>>> to use a sentinel value to say "this really means use the "critical
>>>>> priority" because there is no way to convey a change of scheduling
>>>>> class.
>>>>> It seems to me that we are pretending to have "critical priority"
>>>>> support on all platforms when in reality we don't. If we want to go
>>>>> that way then we should extend it to the
>>>>> UseCriticalJavaThreadPriority case as well. It should be all or 
>>>>> nothing.
>>>> Extend it beyond making CriticalPriority == MaxPriority on non-Solaris
>>>> platforms?
>>>> I.e., we can now change the compiler and CMS thread priority to
>>>> MaxPriority on
>>>> non-Solaris platforms. I don't know how to make CriticalPriority
>>>> higher than that
>>>> on non-Solaris platforms.
>>>>> Further it needs to be made clear that these may still be dependent
>>>>> on the value of ThreadPriorityPolicy.
>>>> I added a comment to the CR to that effect.
>>>>>> -XX:+UseCriticalCompilerThreadPriority
>>>>>> All compiler threads run at critical priority.
>>>>> It should be more clear that UseCriticalCompilerThreadPriority only
>>>>> applies if CompilerThreadPriority is not set. Perhaps there should
>>>>> also be a startup check for both being used?
>>>> I could, but making CompilerThreadPriority rule is what I intended. 
>>>> I'll
>>>> add a comment to globals.hpp and the CR.
>>>>> Thinking more though we really shouldn't need both flags. The basic
>>>>> problem is that the current "api" only supports setting a simple
>>>>> number and to use FX/60 also requires a change of scheduling class.
>>>>> You could add a hack that CompilerThreadPriority=60 means FX/60. Or,
>>>>> as I've suggested in past email we could generalize the format of the
>>>>> option to allow both a scheduling class designator and priority to be
>>>>> passed - that would be a more general mechanism.
>>>> I didn't want to remove CompilerThreadPriority or change it's effect.
>>>> I can file a CR
>>>> to do that though. Current uses of CompilerThreadPriority=60 should
>>>> work like
>>>> they always have.
>>>> I wanted to confine the change as much as possible to Solaris _and_ to
>>>> limit it
>>>> to just scheduling classes where we know we're not likely to provoke
>>>> thread
>>>> starvation. I can file a CR to add the ability to specify a scheduling
>>>> class for
>>>> Java threads. It would probably add 10 switches for scheduling class
>>>> corresponding
>>>> to the existing 10 Java priority switches. I don't have any ideas on
>>>> how to
>>>> designate particular threads for particular class/priorities.
>>>>> Adding a psuedo-priority 11 is just means to work within the current
>>>>> limitations of the priority scheme.
>>>> Correct.
>>>>>> -XX:+UseCriticalCMSThreadPriority
>>>>>> The CMS background thread runs at critical priority.
>>>>> This doesn't make a lot of sense when you consider the comments in
>>>>> src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp 
>>>>> which still states:
>>>>> "Priority should be just less than that of VMThread"
>>>>> This seems to indicate that we don't really understand what the
>>>>> priority relationship between GC threads and the VMThread should be.
>>>> No, we don't. That's why this is experimental.
>>>>> Should we be able to run the VMThread at FX/60?
>>>> Perhaps. It only matters for things like serial gc, which isn't used
>>>> on big iron.
>>>>>> On Solaris, one must in addition use -XX:+UseThreadPriorities to use
>>>>>> native
>>>>>> priorities at all. Otherwise, Hotspot just accepts whatever Solaris
>>>>>> decides.
>>>>> Is it also dependent on the value of ThreadPriorityPolicy? Should it
>>>>> be? Does it make sense to use it with either policy value?
>>>> No, it's not dependent on ThreadPriorityPolicy. Critical priority is
>>>> the same
>>>> no matter what the default MaxPriority java_to_os_priority is. I think
>>>> that's
>>>> the right thing to do.
>>>>>> Before this change, the Solaris implementation could only change
>>>>>> priorities
>>>>>> within the process scheduling class. It didn't change scheduling
>>>>>> classes on
>>>>>> a per-thread basis. I added that capability and used it for the
>>>>>> critical
>>>>>> thread
>>>>>> work. I also fixed a bug where we were using thr_setprio() to 
>>>>>> save the
>>>>>> original native priority during thread creation and reading it back
>>>>>> when
>>>>>> the thread started via thr_getprio(). Since thr_setprio() can change
>>>>>> the
>>>>>> user-supplied priority, this resulted in an unintended (lower) 
>>>>>> priority
>>>>>> being used.
>>>>> I don't quite follow this. We used thr_setprio to set the native OS
>>>>> priority, and we then read it back using thr_getprio and then used
>>>>> that to pass to thr_setprio again (and also set_lwp_priority). If
>>>>> thr_setprio can change the user-supplied priority then it can make
>>>>> that change on the second call too can't it? Does the fact we now
>>>>> have a lwp affect this? I'm curious about the fact we still both use
>>>>> thr_setprio and set the LWP priority directly ???
>>>> Possibly someone like Dave Dice can answer that question. We were
>>>> already using
>>>> both thr_setprio and set_lwp_priority together. Likely that was in
>>>> case set_lwp_priority
>>>> wasn't available.
>>>> thr_setprio takes a value between 0 and 127 and map that to "some
>>>> priority" that
>>>> may not be the same as its argument. You can, for example, pass it 127
>>>> and
>>>> get 60 back from thr_getprio. So if we set it once with 127 and then
>>>> set it again
>>>> with 60, we can ultimately get back 0. Which is what actually used to
>>>> happen.
>>>> Paul
>>>>> Cheers,
>>>>> David
>>>>>> Thanks,
>>>>>> Paul

More information about the hotspot-runtime-dev mailing list