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 18, 2021
1 parent fd35688 commit 5f678ee
Show file tree
Hide file tree
Showing 18 changed files with 338 additions and 69 deletions.
12 changes: 12 additions & 0 deletions src/linux/classes/com/alibaba/wisp/engine/WispControlGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ private WispControlGroup(int cfsQuotaUs, int cfsPeriodUs) {
private final AtomicLong currentPeriodStart;
private final AtomicLong remainQuota;
volatile Boolean destroyed = false;
/**
* totalConsume provides a rough calculation for total cpu time consumed in this group
*/
private long totalConsume = 0;
CountDownLatch destroyLatch = new CountDownLatch(1);

private static class CpuLimit {
Expand Down Expand Up @@ -142,6 +146,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 +281,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,26 @@
package com.alibaba.management;

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

public interface ResourceContainerMXBean extends PlatformManagedObject {
/**
* Get all running containers uniq id as List
* @return all active containers' id
*/
List<Long> getAllContainerIds();

/**
* Get a specific container's constraints by id
* @param id container id
* @return constraints as list
*/
List<Long> getConstraintsById(long id);

/**
* Get the total cpu time consumed by id specified container
* @param id container id
* @return consumed cpu time by nanosecond
*/
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);
}
}
38 changes: 38 additions & 0 deletions src/share/classes/com/alibaba/rcm/ResourceContainerMonitor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.alibaba.rcm;

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.stream.Collectors;
import java.util.stream.StreamSupport;

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

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

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

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

public synchronized static List<Constraint> getConstraintsById(long id) {
AbstractResourceContainer resourceContainer = (AbstractResourceContainer) resourceContainerMap.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,7 +24,10 @@

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 sun.misc.VM;

import java.util.Collections;

Expand All @@ -40,14 +43,21 @@
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;
}

public static AbstractResourceContainer current() {
if (!sun.misc.VM.isBooted()) {
return root();
if (!VM.isBooted()) {
// JLA will be available only after full VM bootstrap.
// before that stage, we assume VM is running in ROOT container.
return ROOT;
}
return SharedSecrets.getJavaLangAccess().getResourceContainer(Thread.currentThread());
}
Expand All @@ -60,17 +70,17 @@ public void run(Runnable command) {
ResourceContainer container = current();
if (container == this) {
command.run();
return;
}
if (container != root()) {
throw new IllegalStateException("must be in root container " +
"before running into non-root container.");
}
attach();
try {
command.run();
} finally {
detach();
} else {
if (container != ROOT) {
throw new IllegalStateException("must be in root container " +
"before running into non-root container.");
}
attach();
try {
command.run();
} finally {
detach();
}
}
}

Expand All @@ -86,6 +96,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 All @@ -100,7 +115,7 @@ private static class RootContainer extends AbstractResourceContainer {
@Override
public void run(Runnable command) {
AbstractResourceContainer container = current();
if (container == root()) {
if (container == ROOT) {
command.run();
return;
}
Expand Down Expand Up @@ -141,5 +156,15 @@ public Iterable<Constraint> getConstraints() {
public void destroy() {
throw new UnsupportedOperationException("destroy() is not supported by root container");
}

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

@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");
}
}
Loading

0 comments on commit 5f678ee

Please sign in to comment.