Skip to content

Commit

Permalink
[Wisp] ResourceContainerMXBean
Browse files Browse the repository at this point in the history
Summary: Add ResourceContainerMXBean, currently only
support CPU resource amount.

Test Plan: jtreg test/com/alibaba/

Reviewed-by: yuleil, zhengxiaolinX

Issue: dragonwell-project/dragonwell8#206
  • Loading branch information
joeyleeeeeee97 authored and joeylee.lz committed Feb 9, 2021
1 parent fd35688 commit 9e88b66
Show file tree
Hide file tree
Showing 18 changed files with 306 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ private WispControlGroup(int cfsQuotaUs, int cfsPeriodUs) {
private final AtomicLong currentPeriodStart;
private final AtomicLong remainQuota;
volatile Boolean destroyed = false;
private long totalConsume = 0;
CountDownLatch destroyLatch = new CountDownLatch(1);

private static class CpuLimit {
Expand Down Expand Up @@ -142,6 +143,7 @@ long calcCpuTicks(WispTask task) {
long usage = System.nanoTime() - task.enterTs;
remainQuota.addAndGet(-usage);
task.enterTs = 0;
totalConsume += usage;
return usage;
}

Expand Down Expand Up @@ -276,6 +278,13 @@ public void destroy() {
}
}

@Override
public Long getConsumedAmount(ResourceType resourceType) {
if (resourceType != ResourceType.CPU_PERCENT)
return 0L;
return totalConsume;
}

@Override
protected void attach() {
super.attach();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.alibaba.management;

import java.lang.management.PlatformManagedObject;
import java.util.List;

public interface ResourceContainerMXBean extends PlatformManagedObject {
List<Long> getAllContainerIds();
List<Long> getConstraintsById(long id);
long getCPUResourceConsumedAmount(long id);
}
4 changes: 4 additions & 0 deletions src/share/classes/com/alibaba/rcm/ResourceContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,8 @@ static ResourceContainer current() {
* Then the container state will become {@link State#DEAD}.
*/
void destroy();

Long getId();

Long getConsumedAmount(ResourceType resourceType);
}
34 changes: 34 additions & 0 deletions src/share/classes/com/alibaba/rcm/ResourceContainerMXBeanImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.alibaba.rcm;

import com.alibaba.management.ResourceContainerMXBean;
import sun.management.Util;

import javax.management.ObjectName;
import java.util.List;
import java.util.stream.Collectors;

public class ResourceContainerMXBeanImpl implements ResourceContainerMXBean {
private final static String TENANT_CONTAINER_MXBEAN_NAME = "com.alibaba.management:type=ResourceContainer";

@Override
public List<Long> getAllContainerIds() {
return ResourceContainerMonitor.getAllContainerIds();
}

@Override
public List<Long> getConstraintsById(long id) {
return ResourceContainerMonitor.getConstraintsById(id).stream().map(c -> c.getValues()[0]).collect(Collectors.toList());
}


@Override
public long getCPUResourceConsumedAmount(long id) {
ResourceContainer container = ResourceContainerMonitor.getContainerById(id);
return container.getConsumedAmount(ResourceType.CPU_PERCENT);
}

@Override
public ObjectName getObjectName() {
return Util.newObjectName(TENANT_CONTAINER_MXBEAN_NAME);
}
}
42 changes: 42 additions & 0 deletions src/share/classes/com/alibaba/rcm/ResourceContainerMonitor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.alibaba.rcm;

import com.alibaba.rcm.Constraint;
import com.alibaba.rcm.ResourceContainer;
import com.alibaba.rcm.internal.AbstractResourceContainer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class ResourceContainerMonitor {
private static Map<Long, ResourceContainer> tenantContainerMap = new HashMap<>();
private static long idGen = 0;

public synchronized static long register(ResourceContainer resourceContainer) {
long id = idGen++;
tenantContainerMap.put(id, resourceContainer);
return id;
}

public synchronized static ResourceContainer getContainerById(long id) {
return tenantContainerMap.get(id);
}

public synchronized static List<Long> getAllContainerIds() {
return new ArrayList<>(tenantContainerMap.keySet());
}

public synchronized static List<Constraint> getConstraintsById(long id) {
AbstractResourceContainer resourceContainer = (AbstractResourceContainer) tenantContainerMap.get(id);
if (resourceContainer == null)
throw new IllegalArgumentException("Invalid ResourceContainer id : " + id);
return StreamSupport
.stream(resourceContainer.getConstraints().spliterator(), false)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

import com.alibaba.rcm.Constraint;
import com.alibaba.rcm.ResourceContainer;
import com.alibaba.rcm.ResourceContainerMonitor;
import com.alibaba.rcm.ResourceType;
import sun.misc.SharedSecrets;

import java.util.Collections;
Expand All @@ -40,6 +42,11 @@
public abstract class AbstractResourceContainer implements ResourceContainer {

protected final static AbstractResourceContainer ROOT = new RootContainer();
final long id;

protected AbstractResourceContainer() {
id = ResourceContainerMonitor.register(this);
}

public static AbstractResourceContainer root() {
return ROOT;
Expand Down Expand Up @@ -86,6 +93,11 @@ protected void attach() {
SharedSecrets.getJavaLangAccess().setResourceContainer(Thread.currentThread(), this);
}

@Override
public Long getId() {
return id;
}

/**
* Detach from this resource container and return to root container.
* <p>
Expand Down Expand Up @@ -141,5 +153,15 @@ public Iterable<Constraint> getConstraints() {
public void destroy() {
throw new UnsupportedOperationException("destroy() is not supported by root container");
}

@Override
public Long getId() {
return null;
}

@Override
public Long getConsumedAmount(ResourceType resourceType) {
return 0L;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ public void destroy() {
throw new UnsupportedOperationException("Should not call TenantResourceContainer::destroy() directly");
}

@Override
public Long getConsumedAmount(ResourceType resourceType) {
throw new UnsupportedOperationException();
}

void destroyImpl() {
if (jgroup != null) {
jgroup.destory();
Expand Down
18 changes: 15 additions & 3 deletions src/share/classes/java/lang/management/PlatformComponent.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;

import com.alibaba.management.TenantContainerMXBean;
import com.alibaba.management.ElasticHeapMXBean;
import com.alibaba.management.WispCounterMXBean;
import com.alibaba.management.*;
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.UnixOperatingSystemMXBean;

Expand Down Expand Up @@ -307,6 +305,20 @@ public List<ElasticHeapMXBean> getMXBeans() {
}),

/**
* Resource Container.
*/
RESOURCE_CONTAINER(
"com.alibaba.management.ResourceContainerMXBean",
"com.alibaba.management", "ResourceContainerMXBean", defaultKeyProperties(),
true,
new MXBeanFetcher<ResourceContainerMXBean>() {
public List<ResourceContainerMXBean> getMXBeans() {
return Collections.singletonList(ManagementFactoryHelper.getResourceContainerMXBean());
}
}),


/**
* Wisp Counter.
*/
WISP_COUNTER(
Expand Down
12 changes: 9 additions & 3 deletions src/share/classes/sun/management/ManagementFactoryHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;

import com.alibaba.management.TenantContainerMXBean;
import com.alibaba.management.ElasticHeapMXBean;
import com.alibaba.management.WispCounterMXBean;
import com.alibaba.management.*;
import com.alibaba.rcm.ResourceContainerMXBeanImpl;
import com.alibaba.tenant.TenantContainerMXBeanImpl;
import com.alibaba.jvm.gc.ElasticHeapMXBeanImpl;
import com.alibaba.wisp.engine.WispCounterMXBeanImpl;
Expand Down Expand Up @@ -74,6 +73,7 @@ public class ManagementFactoryHelper {
private static TenantContainerMXBeanImpl tenantContainerMBean = null;
private static ElasticHeapMXBeanImpl elasticHeapMXBean = null;
private static WispCounterMXBeanImpl wispCounterMBean = null;
private static ResourceContainerMXBean resourceContainerMXBean = null;

public static synchronized ClassLoadingMXBean getClassLoadingMXBean() {
if (classMBean == null) {
Expand Down Expand Up @@ -137,6 +137,12 @@ public static synchronized WispCounterMXBean getWispCounterMXBean() {
}
return wispCounterMBean;
}
public static synchronized ResourceContainerMXBean getResourceContainerMXBean() {
if (resourceContainerMXBean == null) {
resourceContainerMXBean = new ResourceContainerMXBeanImpl();
}
return resourceContainerMXBean;
}

public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
MemoryPoolMXBean[] pools = MemoryImpl.getMemoryPools();
Expand Down
37 changes: 19 additions & 18 deletions test/com/alibaba/rcm/RcmCpuTest.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
/*
* @test
* @library /lib/testlibrary
* @build RcmCpuTest RcmUtils
* @summary test RCM cpu resource control.
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseWisp2 -XX:ActiveProcessorCount=4 RcmCpuTest
*/

import java.lang.Long;
import java.lang.reflect.Field;

import com.alibaba.rcm.RcmUtils;
import com.alibaba.rcm.ResourceContainer;
import com.alibaba.rcm.ResourceType;

import java.security.MessageDigest;

import java.util.Collections;
import java.util.concurrent.FutureTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import static jdk.testlibrary.Asserts.*;
import static jdk.testlibrary.Asserts.assertLT;

public class RcmCpuTest {

Expand All @@ -42,28 +39,32 @@ public Long call() throws Exception {
}

public static void main(String[] args) throws Exception {
Field f = Class.forName("com.alibaba.wisp.engine.WispConfiguration").getDeclaredField("ENABLE_THREAD_AS_WISP");
f.setAccessible(true);
boolean isWispEnabled = f.getBoolean(null);
ResourceContainer rc0 = isWispEnabled ? WispResourceContainerFactory.instance()
.createContainer(Collections.singletonList(ResourceType.CPU_PERCENT.newConstraint(40))) : null;
ResourceContainer rc1 = isWispEnabled ? WispResourceContainerFactory.instance()
.createContainer(Collections.singletonList(ResourceType.CPU_PERCENT.newConstraint(80))) : null;
ResourceContainer rc0 = RcmUtils.createContainer(
ResourceType.CPU_PERCENT.newConstraint(40));
ResourceContainer rc1 = RcmUtils.createContainer(
ResourceType.CPU_PERCENT.newConstraint(80));

taskFactory(1_000_000).call(); // warm up
Callable<Long> task0 = taskFactory(2_000_000);
Callable<Long> task1 = taskFactory(2_000_000);
FutureTask<Long> futureTask0 = new FutureTask<Long>(task0);
FutureTask<Long> futureTask1 = new FutureTask<Long>(task1);
FutureTask<Long> futureTask0 = new FutureTask<>(task0);
FutureTask<Long> futureTask1 = new FutureTask<>(task1);
ExecutorService es = Executors.newFixedThreadPool(4);
es.submit(() -> {
System.out.println("start-0");
rc0.run(futureTask0);
System.out.println("done-0");
});
es.submit(() -> {
System.out.println("start-1");
rc1.run(futureTask1);
System.out.println("done-1");
});
Long duration0 = futureTask0.get();
Long duration1 = futureTask1.get();
double ratio = (double) duration1.longValue() / duration0.longValue();
assertLT(Math.abs(ratio - 0.5), 0.1, "deviation is out of reasonable scope");
es.shutdownNow();

double ratio = (double) duration1 / duration0;
assertLT(Math.abs(ratio - 0.5), 0.10, "deviation is out of reasonable scope");
}
}
59 changes: 59 additions & 0 deletions test/com/alibaba/rcm/RcmMXBeanTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* @test
* @library /lib/testlibrary
* @summary test RcmMXBeanTest
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseWisp2 -XX:ActiveProcessorCount=4 RcmMXBeanTest
*/

import com.alibaba.management.ResourceContainerMXBean;
import com.alibaba.rcm.ResourceContainer;
import com.alibaba.rcm.ResourceType;

import javax.management.MBeanServer;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.Collections;
import com.alibaba.wisp.engine.WispResourceContainerFactory;

import static jdk.testlibrary.Asserts.*;

public class RcmMXBeanTest {
static ResourceContainerMXBean resourceContainerMXBean;

public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
try {
resourceContainerMXBean = ManagementFactory.newPlatformMXBeanProxy(mbs,
"com.alibaba.management:type=ResourceContainer", ResourceContainerMXBean.class);
} catch (IOException e) {
e.printStackTrace();
}

for (int i = 0; i < 3; i++) {
ResourceContainer rc1 = WispResourceContainerFactory.instance()
.createContainer(Collections.singletonList(ResourceType.CPU_PERCENT.newConstraint(80)));

rc1.run(() -> {
new Thread(() -> {
while (true) {
Thread.yield();
}
}).start();
});
Thread.sleep(1000);
}

assertTrue(resourceContainerMXBean.getAllContainerIds().size() == 4);


for (long id : resourceContainerMXBean.getAllContainerIds()) {
if (id != 0) {
assertTrue(resourceContainerMXBean.getConstraintsById(id).size() == 1);
assertEQ(resourceContainerMXBean.getConstraintsById(id).get(0), 80L);
assertGreaterThan(resourceContainerMXBean.getCPUResourceConsumedAmount(id), 0L);
} else {
assertTrue(resourceContainerMXBean.getConstraintsById(id).isEmpty());
}
}
}
}
Loading

0 comments on commit 9e88b66

Please sign in to comment.