-
Notifications
You must be signed in to change notification settings - Fork 720
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specify heap limits as percentage of total memory #1699
Specify heap limits as percentage of total memory #1699
Conversation
The description should contain -XX:MaxRAMPercentage instead of -XX:MaxRAMPercent, same for -XX:InitialRAMPercentage |
3e56d86
to
f921a5c
Compare
Updated the comment, as well as the commit message. |
Discussion question: Do we need full (signed) double parsing for this particular case? If we do it unsigned would be no underflow case to handle. If we need to have general double parsing I am ok with it |
extensions->memoryMax = (usableMemory / 100) * maxRAMPercent; | ||
|
||
/* Hack table to appear that -Xmx was specified */ | ||
memoryParameters[opt_Xmx] = index; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this solution. I believe the option should be parsed and stored in gc extensions. MemoryMax and initialMemorySize should be adjusted at startup properly. I would try to avoid any decisions in parse module.
extensions->initialMemorySize = (usableMemory / 100) * initialRAMPercent; | ||
|
||
/* Hack table to appear that -Xms was specified */ | ||
memoryParameters[opt_Xms] = index; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same as comment for MemoryMax
4945ac1
to
127ca3c
Compare
I have updated the code to avoid signed parsing. @dmitripivkine @DanHeidinga can you please review the changes. |
I have removed WIP from the subject line. |
runtime/gc_modron_startup/mminit.cpp
Outdated
adjustXmxXmsUsingRAMPercent(MM_GCExtensions *extensions, IDATA *memoryParameters) | ||
{ | ||
OMRPORT_ACCESS_FROM_OMRVM(extensions->getOmrVM()); | ||
uint64_t usableMemory = omrsysinfo_get_addressable_physical_memory(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is called already in MM_GCExtensions::computeDefaultMaxHeap. In my opinion you should integrate handling of maxRAMPercent and initialRAMPercent in that code. Please not modify memoryParameters[opt_Xms] and memoryParameters[opt_Xmx]. Let them keep original command line option values if any.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion you should integrate handling of maxRAMPercent and initialRAMPercent in that code.
But computeDefaultMaxHeap()
is called even before we parse gc options in gcParseCommandLineAndInitializeWithValues()
.
Please not modify memoryParameters[opt_Xms] and memoryParameters[opt_Xmx].
Reason for modifying memoryParameters[opt_Xms]
is the code in gcInitializeCalculatedValues()
which sets initialMemorySize
to default value if memoryParameters[opt_Xms]
is not set.
So If I set initialMemorySize
using initialRAMPercentage but don't update memoryParameters[opt_Xms]
, it will get overwritten to default value in gcInitializeCalculatedValues()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I see. What if we call omrsysinfo_get_addressable_physical_memory() once in MM_GCExtensionsBase before computeDefaultMaxHeap() and store it there. So there would be no need to call it again. Use stored value in MM_GCExtensionsBase::computeDefaultMaxHeap() and MM_GCExtensions::computeDefaultMaxHeap() implementations as well as here.
Modification of memoryParameters for opt_Xms and opt_Xmx is not my preferable way (it is a hack). However considering complicate messy logic in mminit.c related with memory parameters adjustments (needs to be cleaned up obviously but not in this PR) I would except this. Do we need to create adjustXmxXmsUsingRAMPercent() function? I would just add these two "if" statements directly instead (as far as there is no other consumers for this logic).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, we should store omrsysinfo_get_addressable_physical_memory() in a MM_GCExtensionsBase.
memoryParameters[opt_maxRAMPercent] = index; | ||
if (memoryParameters[opt_maxRAMPercent] != -1) { | ||
if (extensions->maxRAMPercent > 100) { | ||
result = OPTION_OVERFLOW; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we create something like J9NLS_GC_OPTIONS_DOUBLE_OUT_OF_RANGE (using existing J9NLS_GC_OPTIONS_INTEGER_OUT_OF_RANGE as example)? It would be more informative
4bb3066
to
031b795
Compare
runtime/util_core/j9argscan.c
Outdated
|
||
*result = strtod(*scan_start, &endPtr); | ||
if (ERANGE == errno) { | ||
if (0.0 == *result) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can not do it according spec: http://www.cplusplus.com/reference/cstdlib/strtod/
in case of ERANGE if return is not equal +/- HUGE_VAL (not overflow) this is underflow. The output value in this case is "value whose magnitude is no greater than the smallest normalized positive number" (not necessarily 0.0). If you want to handle it as zero *result should be set 0.0 before return with rc 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per man page of strtod:
If the correct value would cause overflow, plus or minus HUGE_VAL (HUGE_VALF, HUGE_VALL) is returned (according to the sign of the value), and ERANGE is stored in errno. If the correct value would cause underflow, zero is returned and ERANGE is stored in errno.
Based on that I consider it as underflow if *return
is 0.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From: http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtod.html
The Open Group Base Specifications Issue 7, 2018 edition
IEEE Std 1003.1-2017 (Revision of IEEE Std 1003.1-2008)
"If the correct value would cause an underflow, a value whose magnitude is no greater than the smallest normalized positive number in the return type shall be returned and errno set to [ERANGE]."
if ((-1 == memoryParameterTable[opt_Xms]) && (-1 != memoryParameterTable[opt_initialRAMPercent])) { | ||
extensions->initialMemorySize = (uintptr_t)(((double)extensions->usablePhysicalMemory / 100.0) * extensions->initialRAMPercent); | ||
/* Update memory parameter table to appear that -Xms was specified */ | ||
memoryParameterTable[opt_Xms] = memoryParameterTable[opt_initialRAMPercent]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that in case of error related to out-of-range case (<1m for example) output message would mention -Xms option. This fact should be documented at least. Ideally error message should refer to real option whatever it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about updating the message to say " -Xmx (as set by -XX:InitialRAMPercentage)" when -XX:MaxRAMPercentage is being used to set max heap size. Some examples of updated messages:
- Option too large: -Xmx (as set by -XX:InitialRAMPercentage) is too large
- -Xmx (as set by -XX:InitialRAMPercentage) too small, must be at least 1 Mbytes
I can add a function that returns "-Xmx" or "-Xmx (as set by -XX:InitialRAMPercentage) " based on the option being used:
const char *
displayXmsOrInitialRAMPercentage(IDATA* memoryParameters)
{
if ((-1 == memoryParameters[opt_initialRAMPercent])
&& (memoryParameters[opt_Xms] == memoryParameters[opt_initialRAMPercent])
) {
return "-Xms (as set by -XX:InitialRAMPercentage)";
} else {
return "-Xms";
}
}
and we can use this function wherever we are currently displaying "-Xmx".
Does that look fine?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, something like this
if ((-1 == memoryParameterTable[opt_Xmx]) && (-1 != memoryParameterTable[opt_maxRAMPercent])) { | ||
extensions->memoryMax = (uintptr_t)(((double)extensions->usablePhysicalMemory / 100.0) * extensions->maxRAMPercent); | ||
/* Update memory parameter table to appear that -Xmx was specified */ | ||
memoryParameterTable[opt_Xmx] = memoryParameterTable[opt_maxRAMPercent]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that in case of error related to out-of-range case output message would mention -Xmx option. This fact should be documented at least. Ideally error message should refer to real option whatever it is.
5f992ca
to
0ea5491
Compare
@dmitripivkine I updated the code as suggested. Can you please review it. |
runtime/util/vmargs.c
Outdated
option = MAPPING_MAPNAME(j9vm_args, element); | ||
} | ||
|
||
return j9vm_args->actualVMArgs->options[element].optionString + strlen(option); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is check for (NULL == option) missed there? I believe strlen(NULL) will crash, is not it?
getOptionValue() can return NULL in this case and caller might check it to return OPTION_ERROR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added check for (NULL == option)
.
The current users of getOptionValue()
don't need to check for NULL return value as we already ensure that optionName
is not NULL.
0ea5491
to
2489fc8
Compare
if (*valuesBuffer) { | ||
scanStart = &(j9vm_args->actualVMArgs->options[element].optionString[ strlen(*valuesBuffer) ]); | ||
} else { | ||
return OPTION_ERROR; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reviewers: this "else" is not necessary because of check lines 363-364, it is removed in new code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me
@DanHeidinga Would you please do final review? |
Also this feature should be documented. |
Note: Currently Java 8 does not take the amount of RAM to consideration to calculate -Xmx default. It is applicable for Java 9 and higher. The -XX:MaxRAMPercentage option however is applicable for Java 8 so it introduces a way to set -Xmx as a percentage of machine's RAM. |
runtime/util_core/j9argscan.c
Outdated
if (ERANGE == errno) { | ||
if ((HUGE_VAL == *result) || (-HUGE_VAL == *result)) { | ||
/* overflow */ | ||
return 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this return OPTION_OVERFLOW
instead of a magic number? Also, please add this to the function comment.
runtime/util_core/j9argscan.c
Outdated
} | ||
} else if ((0.0 == *result) && (endPtr == *scan_start)) { | ||
/* no conversion */ | ||
return 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this return OPTION_MALFORMED
? Also worth documenting in the function comment.
runtime/util/vmargs.c
Outdated
@@ -629,6 +639,23 @@ optionValueOperations(J9PortLibrary *portLibrary, J9VMInitArgs* j9vm_args, IDATA | |||
return OPTION_OK; | |||
} | |||
|
|||
static char * | |||
getOptionValue(J9VMInitArgs* j9vm_args, IDATA element, const char *optionName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getOptionValue
-> getStartOfOption
? startOfOptionValue
? I'm not a fan of this function name but the alternatives I've suggested aren't great either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to lack of a better name, lets go with getStartOfOptionValue
.
runtime/util/vmargs.c
Outdated
option = MAPPING_MAPNAME(j9vm_args, element); | ||
} | ||
|
||
if (NULL != option) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be a trace assert that option is not null? A null optionName with no mapping is a programming error.
2489fc8
to
b46eb47
Compare
Add options for specifying heap limits in terms of percentage of total memory available to the JVM. Following options are added: 1. -XX:MaxRAMPercentage=N where 0 <= N <= 100.0 This option specifies maximum heap size. If -Xmx is specified, this option is ignored. 2. -XX:InitialRAMPercentage=N where 0 <= N <= 100.0 This option specifies initial heap size. If -Xms is specified, this option is ignored. Closes: eclipse-openj9#1428 Signed-off-by: Ashutosh Mehra <asmehra1@in.ibm.com>
b46eb47
to
a945467
Compare
@DanHeidinga Updated the changes as suggested. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Jenkins test sanity plinux jdk8 |
Jenkins test sanity xlinux jdk8 |
Looks like the CI server is having issues. Once we can build this it can be merged |
jenkins test sanity xlinux jdk8 |
Add options for specifying heap limits in terms of percentage of
total memory available to the JVM.
Following options are added:
This option specifies maximum heap size. If -Xmx is specified, this
option is ignored.
This option specifies initial heap size. If -Xms is specified, this
option is ignored.
Closes: #1428
Signed-off-by: Ashutosh Mehra asmehra1@in.ibm.com