Skip to content
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

Remove manual parsing of JVM options #41962

Merged
merged 6 commits into from May 9, 2019

Conversation

jasontedor
Copy link
Member

@jasontedor jasontedor commented May 8, 2019

This commit removes manual parsing of JVM options when calculating ergonomics. This is to avoid a situation that we parse values differently than the JVM would. In fact, we already have a bug along these lines today. It is possible to start the JVM with the same flag multiple times on the command line. In this case, the last value wins. For example, -Xmx1g -Xmx2g would start the JVM with a heap size of two gigabytes. Our JVM ergonomics ignores this possibility and instead the first value is winning!

Our strategy to avoid manual parsing of the JVM options is to start the Java command line parser (without actually starting a JVM) by invoking java with the same command line flags as presented and request that the JVM tell us what values it would start with. This ensures that we have the correct values when making ergonomic decisions.

Moreover, our strategy also is ignoring ES_JAVA_OPTS which could override the heap size as well leading to incorrect ergonomic choices. This commit address this issue too.

Relates #30684

This commit removes manual parsing of JVM options when calculating
ergonomics. This is to avoid a situation that we parse values
differently than the JVM would. In fact, we already have a bug along
these lines today. It is possible to start the JVM with the same flag
multiple times on the command line. In this case, the last value
wins. For example, -Xmx1g -Xmx2g would start the JVM with a heap size of
two gigabytes. Our JVM ergonomics ignores this possibility and instead
the first value is winning!

Our strategy to avoid manual parsing of the JVM options is to start yet
another JVM with the same command line flags as presented and request
that the JVM tell us what values it would start with. This ensures that
we have the correct values when making ergonomic decisions.

Moreover, our strategy also is ignoring ES_JAVA_OPTS which could
override the heap size as well leading to incorrect ergonomic
choices. This commit address this issue too.
@jasontedor jasontedor added >enhancement :Delivery/Packaging RPM and deb packaging, tar and zip archives, shell and batch scripts v8.0.0 v7.2.0 labels May 8, 2019
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra

@jasontedor
Copy link
Member Author

To my beloved reviewers: This approach was initially suggested on the original work introducing the ergonomics. Please see the discussion there as part of your review before we consider pulling this in. I think that we can revisit the discussion here if needed.

@jasontedor jasontedor added :Core/Infra/Core Core issues without another label and removed :Delivery/Packaging RPM and deb packaging, tar and zip archives, shell and batch scripts labels May 8, 2019
@rjernst
Copy link
Member

rjernst commented May 8, 2019

This seems like a very heavyweight hack. Launching a VM with Xmx pretouched, just to find out what the value was is a huge cost (relative to normal startup).

Both the bugs you mentioned (first vs last wins, missing ES_JAVA_OPTS) seem fixable with the current implementation. IMO keeping our own parsing isn't that expensive vs incurring the added startup cost for every node we start (which amplifies in our integration tests as we start a lot of nodes...).

@jasontedor
Copy link
Member Author

I think there is confusion here, introduced by my commit message (I will reword it); I’m sorry for that. If you refer back to the initial discussion in #30684, we do not actually start a JVM here, only invoke java for options parsing. By requesting -XX:+PrintFlagsFinal -version it only causes the Java process to parse the options, display all the JVM flags, print the version, and exit. The JVM itself never bootstraps. This is actually quite cheap then.

While what we are doing today has bugs that can be fixed without resorting to this, there are bugs we have today that can not. Here’s a list of the bugs we have today:

  • ordering of options
  • ignore ES_JAVA_OPTS
  • wrong value if heap size is not specified (there are use cases for this, in containers)
  • we don’t parse all possible unit specifications

The third of these simply can not be fixed by us. My change fixes all of these, with no additional effort on our end. We don’t have to have a side implementation of the JVM parsing logic.

Additionally, this sets us up to easily extract the value of MaxDirectMemorySize, without having to parse that too.

Thus I maintain this is a superior approach.

@jaymode
Copy link
Member

jaymode commented May 8, 2019

I think there is confusion here, introduced by my commit message (I will reword it)

The semantics of invoking java -XX:+PrintFlagsFinal -version with all the JVM flags we are going to start elasticsearch with is not intuitive enough to only have code without comments IMO; I think we need to spell this out in a code comment and probably cover:

  1. Does not start a JVM and hence does not allocate/pretouch GBs of memory
  2. Only invokes the option parser
  3. Is cheap
  4. Allows us to avoid having our own implementation of JVM option parsing logic

I'm personally in favor of this approach.

@jasontedor
Copy link
Member Author

@jaymode I pushed a comment in 8aed51e.

@rjernst
Copy link
Member

rjernst commented May 9, 2019

we do not actually start a JVM here, only invoke java for options parsing. By requesting -XX:+PrintFlagsFinal -version it only causes the Java process to parse the options, display all the JVM flags, print the version, and exit.

You are right, I completely missed that, I'm sorry. I misinterpreted a comment from Daniel in the previous discussion about startup time of java with 8GB Xmx. Given my new understanding, this approach does sound superior.

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the comment in code, it makes much more sense now.

Copy link
Member

@jaymode jaymode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

…rsing

* elastic/master:
  [ML] relax set upgrade mode test to match what is guaranteed (elastic#41958)
  Add note about ILM action ordering (elastic#41771)
  Remove Version 6 pre-release constants (elastic#41517)
  Mute illegal interval rollup tests
  Add static section whitelist info to api docs generation (elastic#41870)
  Cleanup RollupSearch exceptions, disallow partial results (elastic#41272)
Copy link
Member

@danielmitterdorfer danielmitterdorfer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with the approach. Indeed it seems superior to me.

Additionally, this sets us up to easily extract the value of MaxDirectMemorySize, without having to parse that too.

I think you left out one detail that led me to misinterpret your statement originally. We can properly parse MaxDirectMemorySize provided that the user has specified one. If the user did not specify one, we see a MaxDirectMemorySize of 0 because the JVM determines this value in a much later stage during startup. If I run this:

daniel@io:~ $ java -XX:+PrintFlagsFinal -version | grep MaxDirectMemorySize

I get:

 uint64_t MaxDirectMemorySize                      = 0                                         {product} {default}
openjdk version "12" 2019-03-19
OpenJDK Runtime Environment (build 12+32)
OpenJDK 64-Bit Server VM (build 12+32, mixed mode, sharing)

But as I said: I think your intention was to state that we can parse the user-specified value with this approach as well.

@jasontedor jasontedor merged commit 2592b49 into elastic:master May 9, 2019
jasontedor added a commit that referenced this pull request May 9, 2019
This commit removes manual parsing of JVM options when calculating
ergonomics. This is to avoid a situation that we parse values
differently than the JVM would. In fact, we already have a bug along
these lines today. It is possible to start the JVM with the same flag
multiple times on the command line. In this case, the last value
wins. For example, -Xmx1g -Xmx2g would start the JVM with a heap size of
two gigabytes. Our JVM ergonomics ignores this possibility and instead
the first value is winning!

Our strategy to avoid manual parsing of the JVM options is to start the
Java command line parser (without actually starting a JVM) by invoking
java with the same command line flags as presented and request that the
JVM tell us what values it would start with. This ensures that we have
the correct values when making ergonomic decisions.

Moreover, our strategy also is ignoring ES_JAVA_OPTS which could
override the heap size as well leading to incorrect ergonomic
choices. This commit address this issue too.
@jasontedor jasontedor deleted the fix-jvm-options-parsing branch May 9, 2019 10:44
Megamiun pushed a commit to Megamiun/elasticsearch that referenced this pull request May 18, 2019
This commit removes manual parsing of JVM options when calculating
ergonomics. This is to avoid a situation that we parse values
differently than the JVM would. In fact, we already have a bug along
these lines today. It is possible to start the JVM with the same flag
multiple times on the command line. In this case, the last value
wins. For example, -Xmx1g -Xmx2g would start the JVM with a heap size of
two gigabytes. Our JVM ergonomics ignores this possibility and instead
the first value is winning!

Our strategy to avoid manual parsing of the JVM options is to start the
Java command line parser (without actually starting a JVM) by invoking
java with the same command line flags as presented and request that the
JVM tell us what values it would start with. This ensures that we have
the correct values when making ergonomic decisions.

Moreover, our strategy also is ignoring ES_JAVA_OPTS which could
override the heap size as well leading to incorrect ergonomic
choices. This commit address this issue too.
gurkankaymak pushed a commit to gurkankaymak/elasticsearch that referenced this pull request May 27, 2019
This commit removes manual parsing of JVM options when calculating
ergonomics. This is to avoid a situation that we parse values
differently than the JVM would. In fact, we already have a bug along
these lines today. It is possible to start the JVM with the same flag
multiple times on the command line. In this case, the last value
wins. For example, -Xmx1g -Xmx2g would start the JVM with a heap size of
two gigabytes. Our JVM ergonomics ignores this possibility and instead
the first value is winning!

Our strategy to avoid manual parsing of the JVM options is to start the
Java command line parser (without actually starting a JVM) by invoking
java with the same command line flags as presented and request that the
JVM tell us what values it would start with. This ensures that we have
the correct values when making ergonomic decisions.

Moreover, our strategy also is ignoring ES_JAVA_OPTS which could
override the heap size as well leading to incorrect ergonomic
choices. This commit address this issue too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants