This is an automated email from the ASF dual-hosted git repository. jiajunwang pushed a commit to branch wagedRebalancer in repository https://gitbox.apache.org/repos/asf/helix.git
commit 52e1ba5971afa8ecdf88ceca273bdef6d1098f77 Author: Yi Wang <i3.wan...@gmail.com> AuthorDate: Sat Sep 14 22:09:10 2019 -0700 Implement MaxCapacityUsageInstanceConstraint soft constraint (#463) The constraint evaluates the score by checking the max used capacity key out of all the capacity keys. The higher the maximum usage value for the capacity key, the lower the score will be, implying that it is that much less desirable to assign anything on the given node. It is a greedy approach since it evaluates only the most used capacity key. --- .../InstancePartitionsCountConstraint.java | 1 + ...ava => MaxCapacityUsageInstanceConstraint.java} | 24 +++++----- .../waged/constraints/SoftConstraint.java | 3 +- .../constraints/SoftConstraintWeightModel.java | 2 +- .../TestInstancePartitionsCountConstraint.java | 9 ++-- .../TestMaxCapacityUsageInstanceConstraint.java | 56 ++++++++++++++++++++++ 6 files changed, 78 insertions(+), 17 deletions(-) diff --git a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/InstancePartitionsCountConstraint.java b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/InstancePartitionsCountConstraint.java index ca05cf8..feee05a 100644 --- a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/InstancePartitionsCountConstraint.java +++ b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/InstancePartitionsCountConstraint.java @@ -27,6 +27,7 @@ import org.apache.helix.controller.rebalancer.waged.model.ClusterContext; * Evaluate by instance's current partition count versus estimated max partition count * Intuitively, Encourage the assignment if the instance's occupancy rate is below average; * Discourage the assignment if the instance's occupancy rate is above average + * The normalized score will be within [0, 1] */ class InstancePartitionsCountConstraint extends SoftConstraint { private static final float MAX_SCORE = 1f; diff --git a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/InstancePartitionsCountConstraint.java b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/MaxCapacityUsageInstanceConstraint.java similarity index 61% copy from helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/InstancePartitionsCountConstraint.java copy to helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/MaxCapacityUsageInstanceConstraint.java index ca05cf8..2fe94c6 100644 --- a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/InstancePartitionsCountConstraint.java +++ b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/MaxCapacityUsageInstanceConstraint.java @@ -9,7 +9,7 @@ package org.apache.helix.controller.rebalancer.waged.constraints; * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an @@ -24,24 +24,24 @@ import org.apache.helix.controller.rebalancer.waged.model.AssignableReplica; import org.apache.helix.controller.rebalancer.waged.model.ClusterContext; /** - * Evaluate by instance's current partition count versus estimated max partition count - * Intuitively, Encourage the assignment if the instance's occupancy rate is below average; - * Discourage the assignment if the instance's occupancy rate is above average + * The constraint evaluates the score by checking the max used capacity key out of all the capacity + * keys. + * The higher the maximum usage value for the capacity key, the lower the score will be, implying + * that it is that much less desirable to assign anything on the given node. + * It is a greedy approach since it evaluates only on the most used capacity key. */ -class InstancePartitionsCountConstraint extends SoftConstraint { - private static final float MAX_SCORE = 1f; - private static final float MIN_SCORE = 0f; +class MaxCapacityUsageInstanceConstraint extends SoftConstraint { + private static final float MIN_SCORE = 0; + private static final float MAX_SCORE = 1; - InstancePartitionsCountConstraint() { + MaxCapacityUsageInstanceConstraint() { super(MAX_SCORE, MIN_SCORE); } @Override protected float getAssignmentScore(AssignableNode node, AssignableReplica replica, ClusterContext clusterContext) { - float doubleEstimatedMaxPartitionCount = 2 * clusterContext.getEstimatedMaxPartitionCount(); - float currentPartitionCount = node.getAssignedReplicaCount(); - return Math.max((doubleEstimatedMaxPartitionCount - currentPartitionCount) - / doubleEstimatedMaxPartitionCount, 0); + float maxCapacityUsage = node.getHighestCapacityUtilization(); + return 1.0f - maxCapacityUsage / 2.0f; } } diff --git a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/SoftConstraint.java b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/SoftConstraint.java index 0f2bdbc..f44d262 100644 --- a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/SoftConstraint.java +++ b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/SoftConstraint.java @@ -24,7 +24,8 @@ import org.apache.helix.controller.rebalancer.waged.model.AssignableReplica; import org.apache.helix.controller.rebalancer.waged.model.ClusterContext; /** - * The "soft" constraint evaluates the optimality of an assignment by giving it a score of a scale of [minScore, maxScore] + * The "soft" constraint evaluates the optimality of an assignment by giving it a score of a scale + * of [minScore, maxScore] * The higher the score, the better the assignment; Intuitively, the assignment is encouraged. * The lower score the score, the worse the assignment; Intuitively, the assignment is penalized. */ diff --git a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/SoftConstraintWeightModel.java b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/SoftConstraintWeightModel.java index a961936..953005c 100644 --- a/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/SoftConstraintWeightModel.java +++ b/helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/SoftConstraintWeightModel.java @@ -35,7 +35,7 @@ class SoftConstraintWeightModel { } static { - //TODO update the weight + // TODO update the weight MODEL = ImmutableMap.<Class, Float> builder().put(InstancePartitionsCountConstraint.class, 1.0f) .build(); } diff --git a/helix-core/src/test/java/org/apache/helix/controller/rebalancer/waged/constraints/TestInstancePartitionsCountConstraint.java b/helix-core/src/test/java/org/apache/helix/controller/rebalancer/waged/constraints/TestInstancePartitionsCountConstraint.java index 7ffc40b..63622e2 100644 --- a/helix-core/src/test/java/org/apache/helix/controller/rebalancer/waged/constraints/TestInstancePartitionsCountConstraint.java +++ b/helix-core/src/test/java/org/apache/helix/controller/rebalancer/waged/constraints/TestInstancePartitionsCountConstraint.java @@ -38,7 +38,8 @@ public class TestInstancePartitionsCountConstraint { @Test public void testWhenInstanceIsIdle() { when(_testNode.getAssignedReplicaCount()).thenReturn(0); - float score = _constraint.getAssignmentNormalizedScore(_testNode, _testReplica, _clusterContext); + float score = + _constraint.getAssignmentNormalizedScore(_testNode, _testReplica, _clusterContext); Assert.assertEquals(score, 1.0f); } @@ -46,7 +47,8 @@ public class TestInstancePartitionsCountConstraint { public void testWhenInstanceIsFull() { when(_testNode.getAssignedReplicaCount()).thenReturn(10); when(_clusterContext.getEstimatedMaxPartitionCount()).thenReturn(10); - float score = _constraint.getAssignmentNormalizedScore(_testNode, _testReplica, _clusterContext); + float score = + _constraint.getAssignmentNormalizedScore(_testNode, _testReplica, _clusterContext); Assert.assertEquals(score, 0.5f); } @@ -54,7 +56,8 @@ public class TestInstancePartitionsCountConstraint { public void testWhenInstanceHalfOccupied() { when(_testNode.getAssignedReplicaCount()).thenReturn(10); when(_clusterContext.getEstimatedMaxPartitionCount()).thenReturn(20); - float score = _constraint.getAssignmentNormalizedScore(_testNode, _testReplica, _clusterContext); + float score = + _constraint.getAssignmentNormalizedScore(_testNode, _testReplica, _clusterContext); Assert.assertEquals(score, 0.75f); } } diff --git a/helix-core/src/test/java/org/apache/helix/controller/rebalancer/waged/constraints/TestMaxCapacityUsageInstanceConstraint.java b/helix-core/src/test/java/org/apache/helix/controller/rebalancer/waged/constraints/TestMaxCapacityUsageInstanceConstraint.java new file mode 100644 index 0000000..7026dee --- /dev/null +++ b/helix-core/src/test/java/org/apache/helix/controller/rebalancer/waged/constraints/TestMaxCapacityUsageInstanceConstraint.java @@ -0,0 +1,56 @@ +package org.apache.helix.controller.rebalancer.waged.constraints; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.helix.controller.rebalancer.waged.model.AssignableNode; +import org.apache.helix.controller.rebalancer.waged.model.AssignableReplica; +import org.apache.helix.controller.rebalancer.waged.model.ClusterContext; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class TestMaxCapacityUsageInstanceConstraint { + private AssignableReplica _testReplica; + private AssignableNode _testNode; + private ClusterContext _clusterContext; + private final SoftConstraint _constraint = new MaxCapacityUsageInstanceConstraint(); + + @BeforeMethod + public void setUp() { + _testNode = mock(AssignableNode.class, CALLS_REAL_METHODS); + _testReplica = mock(AssignableReplica.class); + _clusterContext = mock(ClusterContext.class); + } + + @Test + public void testGetNormalizedScore() { + when(_testNode.getHighestCapacityUtilization()).thenReturn(0.8f); + float score = + _constraint.getAssignmentScore(_testNode, _testReplica, _clusterContext); + Assert.assertEquals(score, 0.6f); + float normalizedScore = + _constraint.getAssignmentNormalizedScore(_testNode, _testReplica, _clusterContext); + Assert.assertEquals(normalizedScore, 0.6f); + } +}