HBASE-20914 Trim Master memory usage

Add (weak reference) interning of ServerNames.

Correct Balancer regions x racks matrix.

Make smaller defaults when creating ArrayDeques.
This commit is contained in:
Michael Stack 2018-07-19 15:17:40 -07:00
parent 03e596c669
commit 067388bfd9
5 changed files with 43 additions and 13 deletions

View File

@ -27,9 +27,11 @@ import java.util.regex.Pattern;
import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.net.Address;
import org.apache.hadoop.hbase.util.Addressing; import org.apache.hadoop.hbase.util.Addressing;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hbase.thirdparty.com.google.common.collect.Interner;
import org.apache.hbase.thirdparty.com.google.common.collect.Interners;
import org.apache.hbase.thirdparty.com.google.common.net.InetAddresses;
import org.apache.yetus.audience.InterfaceAudience; import org.apache.yetus.audience.InterfaceAudience;
import org.apache.hbase.thirdparty.com.google.common.net.InetAddresses;
/** /**
@ -99,6 +101,13 @@ public class ServerName implements Comparable<ServerName>, Serializable {
private byte [] bytes; private byte [] bytes;
public static final List<ServerName> EMPTY_SERVER_LIST = new ArrayList<>(0); public static final List<ServerName> EMPTY_SERVER_LIST = new ArrayList<>(0);
/**
* Intern ServerNames. The Set of ServerNames is mostly-fixed changing slowly as Servers
* restart. Rather than create a new instance everytime, try and return existing instance
* if there is one.
*/
private static final Interner<ServerName> INTERN_POOL = Interners.newWeakInterner();
protected ServerName(final String hostname, final int port, final long startcode) { protected ServerName(final String hostname, final int port, final long startcode) {
this(Address.fromParts(hostname, port), startcode); this(Address.fromParts(hostname, port), startcode);
} }
@ -176,7 +185,7 @@ public class ServerName implements Comparable<ServerName>, Serializable {
* a shared immutable object as an internal optimization. * a shared immutable object as an internal optimization.
*/ */
public static ServerName valueOf(final String hostname, final int port, final long startcode) { public static ServerName valueOf(final String hostname, final int port, final long startcode) {
return new ServerName(hostname, port, startcode); return INTERN_POOL.intern(new ServerName(hostname, port, startcode));
} }
/** /**
@ -185,7 +194,7 @@ public class ServerName implements Comparable<ServerName>, Serializable {
* a shared immutable object as an internal optimization. * a shared immutable object as an internal optimization.
*/ */
public static ServerName valueOf(final String serverName) { public static ServerName valueOf(final String serverName) {
return new ServerName(serverName); return INTERN_POOL.intern(new ServerName(serverName));
} }
/** /**
@ -194,7 +203,7 @@ public class ServerName implements Comparable<ServerName>, Serializable {
* a shared immutable object as an internal optimization. * a shared immutable object as an internal optimization.
*/ */
public static ServerName valueOf(final String hostAndPort, final long startCode) { public static ServerName valueOf(final String hostAndPort, final long startCode) {
return new ServerName(hostAndPort, startCode); return INTERN_POOL.intern(new ServerName(hostAndPort, startCode));
} }
@Override @Override

View File

@ -31,4 +31,8 @@ import java.util.ArrayDeque;
*/ */
@InterfaceAudience.Private @InterfaceAudience.Private
public class ProcedureDeque extends ArrayDeque<Procedure> { public class ProcedureDeque extends ArrayDeque<Procedure> {
public ProcedureDeque() {
// Default is 16 for a list that is rarely used; elements will resize if too small.
super(2);
}
} }

View File

@ -566,7 +566,7 @@ public abstract class BaseLoadBalancer implements LoadBalancer {
* and rack have the highest locality for region * and rack have the highest locality for region
*/ */
private void computeCachedLocalities() { private void computeCachedLocalities() {
rackLocalities = new float[numRegions][numServers]; rackLocalities = new float[numRegions][numRacks];
regionsToMostLocalEntities = new int[LocalityType.values().length][numRegions]; regionsToMostLocalEntities = new int[LocalityType.values().length][numRegions];
// Compute localities and find most local server per region // Compute localities and find most local server per region

View File

@ -532,8 +532,7 @@ public class StochasticLoadBalancer extends BaseLoadBalancer {
sm.getRegionMetrics().forEach((byte[] regionName, RegionMetrics rm) -> { sm.getRegionMetrics().forEach((byte[] regionName, RegionMetrics rm) -> {
Deque<BalancerRegionLoad> rLoads = oldLoads.get(Bytes.toString(regionName)); Deque<BalancerRegionLoad> rLoads = oldLoads.get(Bytes.toString(regionName));
if (rLoads == null) { if (rLoads == null) {
// There was nothing there rLoads = new ArrayDeque<>(numRegionLoadsToRemember + 1);
rLoads = new ArrayDeque<>();
} else if (rLoads.size() >= numRegionLoadsToRemember) { } else if (rLoads.size() >= numRegionLoadsToRemember) {
rLoads.remove(); rLoads.remove();
} }

View File

@ -20,16 +20,19 @@ package org.apache.hadoop.hbase;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.hadoop.hbase.testclassification.MiscTests; import org.apache.hadoop.hbase.testclassification.MiscTests;
import org.apache.hadoop.hbase.testclassification.SmallTests; import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.apache.hadoop.hbase.util.Addressing; import org.apache.hadoop.hbase.util.Addressing;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
import org.junit.ClassRule; import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.experimental.categories.Category; import org.junit.experimental.categories.Category;
@ -86,7 +89,8 @@ public class TestServerName {
ServerName.parseServerName("192.168.1.199:58102"); ServerName.parseServerName("192.168.1.199:58102");
} }
@Test public void testParseOfBytes() { @Test
public void testParseOfBytes() {
final String snStr = "www.EXAMPLE.org,1234,5678"; final String snStr = "www.EXAMPLE.org,1234,5678";
ServerName sn = ServerName.valueOf(snStr); ServerName sn = ServerName.valueOf(snStr);
byte[] versionedBytes = sn.getVersionedBytes(); byte[] versionedBytes = sn.getVersionedBytes();
@ -132,5 +136,19 @@ public class TestServerName {
assertTrue(upper.equals(lower)); assertTrue(upper.equals(lower));
assertTrue(ServerName.isSameAddress(lower, upper)); assertTrue(ServerName.isSameAddress(lower, upper));
} }
@Test
public void testInterning() {
ServerName sn1 = ServerName.valueOf("www.example.org", 1234, 5671);
assertSame(sn1, ServerName.valueOf("www.example.org", 1234, 5671));
}
@Ignore // Enable and let fun for hours to make sure weak references working fine.
@Test
public void testInterningDoesWeakReferences() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
ServerName.valueOf("www.example.org", 1234, i++);
}
}
} }