-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Centralize the concept of processors configuration #89662
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
Conversation
a047e87 to
e5d90ae
Compare
e5d90ae to
46ebfc1
Compare
|
@elasticmachine run elasticsearch-ci/bwc |
|
Pinging @elastic/es-distributed (Team:Distributed) |
|
Hi @fcofdez, I've created a changelog YAML for you. |
henningandersen
left a comment
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 went through the production code and left comments.
|
|
||
| @Override | ||
| public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
| return builder.value(count); |
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.
Could this produce more than 5 decimals?
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.
count is already truncated to 5 decimal places in the constructor. Additionally, there's a test (ProcessorsTests#testTruncatesAfterFiveDecimalPlaces) that checks that the string representation has up to 5 decimal places.
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 tried to read Double.toString. IIUC, we would get scientific notation for numbers less than 1e-3? Maybe not a problem though, I suppose it is json compatible.
I also worry that there is some number, where even when rounded to 5 decimal places we need more decimals to represent it uniquely. I do not have an example, but did you run the test thousands of times to check?
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 tried to read Double.toString. IIUC, we would get scientific notation for numbers less than 1e-3? Maybe not a problem though, I suppose it is json compatible.
According to RFC-8259 the scientific notation should be supported by any standard parser.
I also worry that there is some number, where even when rounded to 5 decimal places we need more decimals to represent it uniquely. I do not have an example, but did you run the test thousands of times to check?
I improved the test and I've run it 10K times.
| } | ||
|
|
||
| private static boolean validNumberOfProcessors(double processors) { | ||
| return Double.isFinite(processors) && processors >= 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.
Do we need to support 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.
Hmm, now seeing this is indeed needed for autoscaling. Sad, I wish we could find another way there, but that is for another day.
But can we ensure that only the ZERO constant can create a 0.0 value by having a special private constructor?
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 we remove 0.0 as a valid number now?
| return Double.isFinite(processors) && processors >= 0.0; | |
| return Double.isFinite(processors) && processors > 0.0; |
|
|
||
| public class TransportUpdateDesiredNodesAction extends TransportMasterNodeAction<UpdateDesiredNodesRequest, UpdateDesiredNodesResponse> { | ||
| private static final Logger logger = LogManager.getLogger(TransportUpdateDesiredNodesAction.class); | ||
| private static final double MAX_DELTA_PROCESSORS = 7E-5; |
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 is a magic constant, how did you come to this? Would this also work for 128 processors for instance?
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 run quite a few experiments in DesiredNodeTests#testFloatProcessorsConvertedToDoubleAreCloseToEqual starting from 1E-5 but that failed quite a few times. I increased it by 1E-5 at a time until the test stopped failing. I agree that's not super scientific method.
| float floatCount = (float) a.count(); | ||
| float otherFloatCount = (float) b.count(); | ||
| return Float.isFinite(floatCount) && Float.isFinite(otherFloatCount) && (Math.abs(floatCount - otherFloatCount) < maxError); |
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 we instead use Math.max(Math.ulp(floatCount), Math.ulp(otherFloatCount)) + MIN_REPRESENTABLE_PROCESSORS as the error bound? Or has the number been rounded during x-content too?
I also wonder if we can be slightly more precise since we could know that the new number originates from a double? Might not be worth it though...
| private final long refreshInterval; | ||
| private final int availableProcessors; | ||
| private final int allocatedProcessors; | ||
| private final Processors allocatedProcessors; |
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 suppose this changes our nodes x-content output to have double processors. I wonder if we need to consider that a breaking change, since it could break downstream clients?
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.
Good point, I'll serialize the rounded allocated processors in x-content. I wonder if we want to serialize the fractional value in an additional field.
| Integer roundedUpMaxProcessors = node.roundedUpMaxProcessors(); | ||
| int maxProcessors = roundedUpMaxProcessors == null ? minProcessors : roundedUpMaxProcessors; | ||
| Setting.intSetting(NODE_PROCESSORS_SETTING.getKey(), minProcessors, 1, maxProcessors, Setting.Property.NodeScope).get(settings); | ||
| Setting.doubleSetting(NODE_PROCESSORS_SETTING.getKey(), minProcessors, 1, maxProcessors, Setting.Property.NodeScope) |
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 lower the minValue to Double.MIN_VALUE or Processors.MIN_REPRESENTABLE_PROCESSORS?
| private static int roundDown(float value) { | ||
| return Math.max(1, (int) Math.floor(value)); | ||
| private static boolean invalidNumberOfProcessors(Processors processors) { | ||
| return processors != null && processors.count() <= 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.
I think this can only be true for processors.count() == 0 now, but is that even a legal case for Processors? Given that we now validate Processors separately perhaps this method is no longer needed?
| } | ||
|
|
||
| @Nullable | ||
| public static Processors of(Double count) { |
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 wonder if we should move all Processors construction to use an of method, just to simplify and avoid mistakes? That of method could hold the validation too then, helping on the ZERO part I commented on in another comment (though a minor point).
| builder.node(MINIMUM_FROZEN_STORAGE, MINIMUM_FROZEN_MEMORY, null); | ||
| } else { | ||
| builder.total(0L, 0L, 0f); | ||
| builder.total(ByteSizeValue.ZERO, ByteSizeValue.ZERO, null); |
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 use Processors.ZERO instead of null?
| } | ||
|
|
||
| public static Processors randomProcessors() { | ||
| return Processors.of(randomInt(128) + randomDouble()); |
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.
nit: can we use randomDoubleBetween?
|
@henningandersen could you review this when you have the chance? Thanks! |
henningandersen
left a comment
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.
| } | ||
|
|
||
| private static boolean validNumberOfProcessors(double processors) { | ||
| return Double.isFinite(processors) && processors >= 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.
Can we remove 0.0 as a valid number now?
| return Double.isFinite(processors) && processors >= 0.0; | |
| return Double.isFinite(processors) && processors > 0.0; |
| } | ||
|
|
||
| private double randomNumberOfProcessors() { | ||
| return randomDoubleBetween(Math.ulp(0.0), 512.99999999, true); |
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 Math.ulp(0.0) not the same as Double.MIN_VALUE? I'd prefer to use the latter then.
| } | ||
|
|
||
| public static double randomNumberOfProcessors() { | ||
| return randomDoubleBetween(Math.ulp(0.0), 512.99999999, true); |
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.
Also use Double.MIN_VALUE here?
|
|
||
| @Override | ||
| protected Processors createTestInstance() { | ||
| return Processors.of(randomDoubleBetween(Math.ulp(0.0), 512.99999999, true)); |
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.
Also use Double.MIN_VALUE here?
| } | ||
|
|
||
| public void testRounding() { | ||
| { |
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 we add 1-2 more cases:
- A number higher than 1.something, for instance 10.1.
- A number that is already an integer, for instance 10.
| import static org.hamcrest.Matchers.lessThanOrEqualTo; | ||
|
|
||
| public class ProcessorsTests extends ESTestCase { | ||
| public void testTruncatesAfterFiveDecimalPlaces() { |
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 completeness, can we add a test that Processors.of(value).count() == value?
.../org/elasticsearch/xpack/autoscaling/capacity/AutoscalingCapacityWireSerializationTests.java
Show resolved
Hide resolved
|
Thanks Henning! |
This commit centralizes the processor count concept into the
Processorsclass.With this change now all the places using a processor count rely on this new class,
such as desired nodes,
node.processorssetting and autoscaling deciders.Desired nodes processors were stored as floats, this poses some challenges during
upgrades as once the value is casted to a double, the precision increases and therefore
the number is not the same. In order to allow idempotent desired nodes updates after
upgrades, this commit introduces
DesiredNode#equalsWithProcessorsCloseTo(DesiredNode that, double maxError)which allows comparing two desired nodes that differ up to
maxErrorin their processorspecification as floats.