liuml07 commented on a change in pull request #2044: URL: https://github.com/apache/hbase/pull/2044#discussion_r456747846
########## File path: hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java ########## @@ -284,6 +284,25 @@ public void testLocalityCost() throws Exception { } } + @Test + public void testMoveCostMultiplier() throws Exception { + Configuration conf = HBaseConfiguration.create(); + StochasticLoadBalancer.CostFunction + costFunction = new StochasticLoadBalancer.MoveCostFunction(conf); + BaseLoadBalancer.Cluster cluster = mockCluster(clusterStateMocks[0]); + costFunction.init(cluster); + costFunction.cost(); + assertEquals(7, costFunction.getMultiplier(), 0.01); Review comment: Not sure if we want to replace 7 with `DEFAULT_MOVE_COST`, which currently is private...same to `DEFAULT_MOVE_COST_OFFPEAK` ########## File path: hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java ########## @@ -827,26 +828,34 @@ protected double scale(double min, double max, double value) { */ static class MoveCostFunction extends CostFunction { private static final String MOVE_COST_KEY = "hbase.master.balancer.stochastic.moveCost"; + private static final String MOVE_COST_OFFPEAK_KEY = "hbase.master.balancer.stochastic.moveCost.offpeak"; private static final String MAX_MOVES_PERCENT_KEY = "hbase.master.balancer.stochastic.maxMovePercent"; - private static final float DEFAULT_MOVE_COST = 7; + @VisibleForTesting + protected static final float DEFAULT_MOVE_COST = 7; + protected static final float DEFAULT_MOVE_COST_OFFPEAK = 3; private static final int DEFAULT_MAX_MOVES = 600; private static final float DEFAULT_MAX_MOVE_PERCENT = 0.25f; private final float maxMovesPercent; + private final Configuration conf; MoveCostFunction(Configuration conf) { super(conf); - - // Move cost multiplier should be the same cost or higher than the rest of the costs to ensure - // that large benefits are need to overcome the cost of a move. - this.setMultiplier(conf.getFloat(MOVE_COST_KEY, DEFAULT_MOVE_COST)); + this.conf = conf; // What percent of the number of regions a single run of the balancer can move. maxMovesPercent = conf.getFloat(MAX_MOVES_PERCENT_KEY, DEFAULT_MAX_MOVE_PERCENT); } @Override protected double cost() { + // Move cost multiplier should be the same cost or higher than the rest of the costs to ensure + // that large benefits are need to overcome the cost of a move. + if (OffPeakHours.getInstance(conf).isOffPeakHour()) { + this.setMultiplier(conf.getFloat(MOVE_COST_OFFPEAK_KEY, DEFAULT_MOVE_COST_OFFPEAK)); + } else { + this.setMultiplier(conf.getFloat(MOVE_COST_KEY, DEFAULT_MOVE_COST)); + } Review comment: @virajjasani Good question. I glimpsed and I guess what @bsglz meant is every time calling the `MoveCostFunction::cost()` function against the same `MoveCostFunction` object should get a different value per the config and the current time. Since this `MoveCostFunction` object is constructed once, the multiplier should be updated here. We can not move the whole if condition to constructor. Updating the `config` object dynamically is another use case (which should also work). Correct me if I'm wrong @bsglz . That said, to remove `this.conf = conf` dependency, we can get two multipliers from config, and call `setMultiplier()` accordingly here in `cost()` by checking `isOffPeakHour()`. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org