JVM Flag ergonomics and constraints
David Holmes
david.holmes at oracle.com
Tue Feb 7 00:48:30 UTC 2023
On 7/02/2023 3:19 am, Ioi Lam wrote:
>
>
> On 2/5/2023 11:45 PM, David Holmes wrote:
>> On 6/02/2023 5:26 pm, Ioi Lam wrote:
>>> On 2/3/2023 12:40 AM, David Holmes wrote:
>>>> On 3/02/2023 5:12 pm, Ioi Lam wrote:
>>>>>
>>>>>
>>>>> On 2/1/2023 10:37 PM, David Holmes wrote:
>>>>>> <trimming>
>>>>>>
>>>>>> On 2/02/2023 3:25 pm, Thomas Stüfe wrote:
>>>>>>> On Thu, Feb 2, 2023 at 5:30 AM David Holmes
>>>>>>> <david.holmes at oracle.com <mailto:david.holmes at oracle.com>> wrote:
>>>>>>>
>>>>>>> That would have to be determined case-by-case. For each ergo
>>>>>>> flag we
>>>>>>> would have to decide what value it is calculating and based
>>>>>>> on what,
>>>>>>> and
>>>>>>> determine whether an out-of-range value is an error or
>>>>>>> something to be
>>>>>>> wary of.
>>>>>>>
>>>>>>> Sure, what I meant was how to control it? Two sets of
>>>>>>> FLAT_SET_... macros, one that asserts on constraint violation,
>>>>>>> one that caps?
>>>>>>
>>>>>> No I expect to just see the places where FLAG_SET_ERGO is called
>>>>>> do the right thing by checking the return value and proceeding
>>>>>> accordingly.
>>>>>
>>>>> David, are you proposing this?
>>>>>
>>>>> int value = calculate_ergo();
>>>>> if (FLAG_SET_ERGO (TheFlag, value) == error) {
>>>>> value = do_it_again()
>>>>> if (FLAG_SET_ERGO (TheFlag, value) == error) {
>>>>> huh?
>>>>> }
>>>>> }
>>>>>
>>>>> In the above code, all FLAG_SET_ERGO does is to check the range for
>>>>> you. It doesn't tell you why the range check fails. So the caller
>>>>> would have to redo the calculation (with no more information, other
>>>>> than that the last value was no good). What if the new value is
>>>>> also no good?
>>>>
>>>> To me that indicates we don't know what the heck we are calculating!
>>>> How can you calculate a setting for a flag if you don't even
>>>> understand the valid range of that flag. Which may mean the max, for
>>>> example, needs to be exposed programmatically.
>>>>
>>>>> With this style, you almost have to wrap every FLAG_SET_ERGO in a
>>>>> loop, keep trying (in the dark) until you succeed.
>>>>>
>>>>> ==================
>>>>> I think it's better to just assert inside FLAG_SET_ERGO if the
>>>>> value is out of range. The caller should make sure it has
>>>>> calculated a correct value.
>>>>
>>>> If the calculation uses some externally settable value then an
>>>> assert won't help if we're in a product build.
>>>>
>>>
>>> We have lots of set_xxx() APIs in various classes that assert when
>>> given an inappropriate value -- this indicates a programming error.
>>> So FLAG_SET_ERGO would be no different.
>>>
>>> It's the responsibility of the caller of FLAG_SET_ERGO to pass a
>>> correct value to FLAG_SET_ERGO . How the caller comes up with that
>>> value (whether it depends on some external input) is irrelevant.
>>> ========
>>>
>>> To properly catch the programming errors with ERGO setting, we should:
>>>
>>> - Change FLAG_SET_ERGO to return "void". The current API gives the
>>> false impression that the caller needs to check the returned value
>>> and do something about it.
>>
>> That's because they do! You still need to be able to report an error
>> for product builds if the value is being calculated based on some
>> passed in runtime value.
>>
>
> That should be done by the code that calls FLAG_SET_ERGO, not by
> FLAG_SET_ERGO itself. E.g., if an environment variable would cause an
> invalid ERGO setting, the code that handles this variable should report
> an error and should NOT call FLAG_SET_ERGO with an invalid value.
I'm not asking FLAG_SET_ERGO to report a specific error, just that the
supplied value was out-of-range. Your position, as stated, is that the
caller should validate everything before calling FLAG_SET_ERGO. My
position was that we could still support a usage pattern where we assume
everything will be fine and we recover if it is not e.g.
newVal = simpleCalc(x, y, z); // works 99% of time
if (!FLAG_SET_ERGO(flag, newVal)) {
newVal = complexCalc(x, y, z); // guarantees in range
FLAG_SET_ERGO(flag, newVal);
}
With what you propose the caller has to range-check newVal, and then
FLAG_SET_ERGO will range-check it again.
> FLAG_SET_ERGO knows nothing about such env variables and cannot print
> out a meaningful error message.
I'm not wanting it to print anything.
David
-----
>
>
>> Putting in an assert is fine but not sufficient.
>>
>> David
>> -----
>>
>>> - Assert if the value is out of range, so we can catch the
>>> programming error during testing (with debug builds)
>>>
>>> It's up to the caller of FLAG_SET_ERGO to determine a value that's
>>> within the allowed range.
>>>
>>> If the caller wants to query the constraints of the flag that it
>>> wants to set, that can be done via the JVMFlagLimit API. Using
>>> JVMFlagLimit is much better than blindly setting a value and getting
>>> an error code that doesn't tell you why it failed.
>>>
>>>
>>>> As I said it depends on exactly what we are using to do the
>>>> calculation. If it is "closed world" then it is a fatal error to get
>>>> it wrong and should be detected during testing. Otherwise the code
>>>> has to deal with the possibility of error.
>>>>
>>>>>
>>>>> Maybe we can add a new FLAG_SET_ERGO_CAPPED() that would cap the
>>>>> value, but that should be an opt-in. FLAG_SET_ERGO() should not
>>>>> automatically cap the value.
>>>>
>>>> That might be suitable for some flags/calculations.
>>>>
>>>> I don't like trying to talk about this in generalities. Each
>>>> specific situation needs to be examined to understand what is being
>>>> calculated and how. But it is the callers of FLAG_SET_ERGO that need
>>>> to know what they are doing.
>>>>
>>>> Cheers,
>>>> David
>>>>
>>>>>
>>>>> Thanks
>>>>> - Ioi
>>>>>
>>>
>
More information about the hotspot-dev
mailing list