Skip to content

Commit

Permalink
ARTEMIS-4809 Allow configuring initial queue buffer size
Browse files Browse the repository at this point in the history
In some setups, there could be a few hundred thousand queues that are
created due to many consumers that are connecting. However, most of
these are empty and stay empty for the entire day since there aren't
necessarily messages to be sent. The 8K intermediateMessageReferences
instantiates an 64KB buffer (Object[]). This means we have large
allocation and live heap that ultimately remains empty for almost the
entire day.

In this commit, we introduce initial-queue-buffer-size, which defaults
to the current value of 8192. It can be set programmatically via
QueueConfiguration#setInitialQueueBufferSize(int).

Note that this must be a positive power of 2.
  • Loading branch information
joshb1050 committed Aug 2, 2024
1 parent 4d8ccc4 commit efa781b
Show file tree
Hide file tree
Showing 22 changed files with 135 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,8 @@ public static String getDefaultHapolicyBackupStrategy() {

public static final long DEFAULT_GLOBAL_MAX_MESSAGES = -1;

public static final int INITIAL_QUEUE_BUFFER_SIZE = 8192;

public static final int DEFAULT_MAX_DISK_USAGE;

static {
Expand Down Expand Up @@ -1967,4 +1969,10 @@ public static boolean getDefaultMirrorPageTransaction() {
return DEFAULT_MIRROR_PAGE_TRANSACTION;
}

/**
* the initial size of the intermediate message buffer used for queues
*/
public static int getInitialQueueBufferSize() {
return INITIAL_QUEUE_BUFFER_SIZE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,11 @@ public final class AddressSettingsInfo {
}
private boolean enableMetrics;

static {
META_BEAN.add(Integer.class, "initialQueueBufferSize", (t, p) -> t.initialQueueBufferSize = p, t -> t.initialQueueBufferSize);
}
private int initialQueueBufferSize;


public static AddressSettingsInfo fromJSON(final String jsonString) {
AddressSettingsInfo newInfo = new AddressSettingsInfo();
Expand Down Expand Up @@ -554,5 +559,9 @@ public long getMaxExpiryDelay() {
public boolean isEnableMetrics() {
return enableMetrics;
}

public int getInitialQueueBufferSize() {
return initialQueueBufferSize;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ public interface Validator<T> {
}
};

public static final Validator<Number> POSITIVE_POWER_OF_TWO = (name, value) -> {
if ((value.longValue() & (value.longValue() - 1)) == 0 && value.longValue() > 0) {
return value;
} else {
throw ActiveMQMessageBundle.BUNDLE.positivePowerOfTwo(name, value);
}
};

public static final Validator<Number> MINUS_ONE_OR_POSITIVE_INT = (name, value) -> {
if (value.longValue() == -1 || (value.longValue() > 0 && value.longValue() <= Integer.MAX_VALUE)) {
return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
import static org.apache.activemq.artemis.core.config.impl.Validators.PERCENTAGE;
import static org.apache.activemq.artemis.core.config.impl.Validators.PERCENTAGE_OR_MINUS_ONE;
import static org.apache.activemq.artemis.core.config.impl.Validators.POSITIVE_INT;
import static org.apache.activemq.artemis.core.config.impl.Validators.POSITIVE_POWER_OF_TWO;
import static org.apache.activemq.artemis.core.config.impl.Validators.ROUTING_TYPE;
import static org.apache.activemq.artemis.core.config.impl.Validators.SLOW_CONSUMER_POLICY_TYPE;
import static org.apache.activemq.artemis.core.config.impl.Validators.SLOW_CONSUMER_THRESHOLD_MEASUREMENT_UNIT;
Expand Down Expand Up @@ -388,6 +389,8 @@ public final class FileConfigurationParser extends XMLConfigurationUtil {

private static final String MIRROR_PAGE_TRANSACTION = "mirror-page-transaction";

private static final String INITIAL_QUEUE_BUFFER_SIZE = "initial-queue-buffer-size";

private boolean validateAIO = false;

private boolean printPageMaxSizeUsed = false;
Expand Down Expand Up @@ -1472,6 +1475,8 @@ protected Pair<String, AddressSettings> parseAddressSettings(final Node node) {
addressSettings.setEnableIngressTimestamp(XMLUtil.parseBoolean(child));
} else if (ID_CACHE_SIZE.equalsIgnoreCase(name)) {
addressSettings.setIDCacheSize(GE_ZERO.validate(ID_CACHE_SIZE, XMLUtil.parseInt(child)).intValue());
} else if (INITIAL_QUEUE_BUFFER_SIZE.equalsIgnoreCase(name)) {
addressSettings.setInitialQueueBufferSize(POSITIVE_POWER_OF_TWO.validate(INITIAL_QUEUE_BUFFER_SIZE, XMLUtil.parseInt(child)).intValue());
}
}
return setting;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,4 +559,6 @@ IllegalStateException invalidRoutingTypeUpdate(String queueName,
@Message(id = 229255, value = "Bridge {} cannot be {}. Current state: {}")
ActiveMQIllegalStateException bridgeOperationCannotBeExecuted(String bridgeName, String failedOp, BridgeImpl.State currentState);

@Message(id = 229256, value = "{} must be a positive power of 2 (actual value: {})")
IllegalArgumentException positivePowerOfTwo(String name, Number val);
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ default void setSwept(boolean sweep) {

long getRingSize();

int getInitialQueueBufferSize();

default boolean isMirrorController() {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ public class QueueImpl extends CriticalComponentImpl implements Queue {
// Messages will first enter intermediateMessageReferences
// Before they are added to messageReferences
// This is to avoid locking the queue on the producer
private final MpscUnboundedArrayQueue<MessageReference> intermediateMessageReferences = new MpscUnboundedArrayQueue<>(8192);
private final MpscUnboundedArrayQueue<MessageReference> intermediateMessageReferences;

// This is where messages are stored
protected final PriorityLinkedList<MessageReference> messageReferences = new PriorityLinkedListImpl<>(QueueImpl.NUM_PRIORITIES, MessageReferenceImpl.getSequenceComparator());
Expand Down Expand Up @@ -365,6 +365,8 @@ private void checkIDSupplier(NodeStoreFactory<MessageReference> nodeStoreFactory

private volatile long createdTimestamp = -1;

private final int initialQueueBufferSize;

@Override
public boolean isSwept() {
return swept;
Expand Down Expand Up @@ -753,6 +755,11 @@ public QueueImpl(final QueueConfiguration queueConfiguration,
}

this.ringSize = queueConfiguration.getRingSize() == null ? ActiveMQDefaultConfiguration.getDefaultRingSize() : queueConfiguration.getRingSize();

this.initialQueueBufferSize = this.addressSettings.getInitialQueueBufferSize() == null
? ActiveMQDefaultConfiguration.INITIAL_QUEUE_BUFFER_SIZE
: this.addressSettings.getInitialQueueBufferSize();
this.intermediateMessageReferences = new MpscUnboundedArrayQueue<>(initialQueueBufferSize);
}

// Bindable implementation -------------------------------------------------------------------------------------
Expand Down Expand Up @@ -1092,6 +1099,11 @@ public RoutingType getRoutingType() {
return routingType;
}

@Override
public int getInitialQueueBufferSize() {
return this.initialQueueBufferSize;
}

@Override
public void setRoutingType(RoutingType routingType) {
if (addressInfo.getRoutingTypes().contains(routingType)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,12 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
static {
metaBean.add(Integer.class, "queuePrefetch", (t, p) -> t.queuePrefetch = p, t -> t.queuePrefetch);
}

static {
metaBean.add(Integer.class, "initialQueueBufferSize", (t, p) -> t.initialQueueBufferSize = p, t -> t.initialQueueBufferSize);
}
private Integer initialQueueBufferSize = null;

//from amq5
//make it transient
@Deprecated
Expand Down Expand Up @@ -1283,6 +1289,15 @@ public AddressSettings setIDCacheSize(int idCacheSize) {
return this;
}

public Integer getInitialQueueBufferSize() {
return initialQueueBufferSize;
}

public AddressSettings setInitialQueueBufferSize(int initialQueueBufferSize) {
this.initialQueueBufferSize = initialQueueBufferSize;
return this;
}

/**
* Merge two AddressSettings instances in one instance
*
Expand Down Expand Up @@ -1783,6 +1798,9 @@ public boolean equals(Object o) {
return false;
if (!Objects.equals(idCacheSize, that.idCacheSize))
return false;
if (!Objects.equals(initialQueueBufferSize, that.initialQueueBufferSize)) {
return false;
}
return Objects.equals(queuePrefetch, that.queuePrefetch);
}

Expand Down Expand Up @@ -1865,11 +1883,13 @@ public int hashCode() {
result = 31 * result + (enableIngressTimestamp != null ? enableIngressTimestamp.hashCode() : 0);
result = 31 * result + (idCacheSize != null ? idCacheSize.hashCode() : 0);
result = 31 * result + (queuePrefetch != null ? queuePrefetch.hashCode() : 0);
result = 31 * result + (initialQueueBufferSize != null ? initialQueueBufferSize.hashCode() : 0);
return result;
}

@Override
public String toString() {
return "AddressSettings{" + "addressFullMessagePolicy=" + addressFullMessagePolicy + ", maxSizeBytes=" + maxSizeBytes + ", maxReadPageBytes=" + maxReadPageBytes + ", maxReadPageMessages=" + maxReadPageMessages + ", prefetchPageBytes=" + prefetchPageBytes + ", prefetchPageMessages=" + prefetchPageMessages + ", pageLimitBytes=" + pageLimitBytes + ", pageLimitMessages=" + pageLimitMessages + ", pageFullMessagePolicy=" + pageFullMessagePolicy + ", maxSizeMessages=" + maxSizeMessages + ", pageSizeBytes=" + pageSizeBytes + ", pageMaxCache=" + pageCacheMaxSize + ", dropMessagesWhenFull=" + dropMessagesWhenFull + ", maxDeliveryAttempts=" + maxDeliveryAttempts + ", messageCounterHistoryDayLimit=" + messageCounterHistoryDayLimit + ", redeliveryDelay=" + redeliveryDelay + ", redeliveryMultiplier=" + redeliveryMultiplier + ", redeliveryCollisionAvoidanceFactor=" + redeliveryCollisionAvoidanceFactor + ", maxRedeliveryDelay=" + maxRedeliveryDelay + ", deadLetterAddress=" + deadLetterAddress + ", expiryAddress=" + expiryAddress + ", expiryDelay=" + expiryDelay + ", minExpiryDelay=" + minExpiryDelay + ", maxExpiryDelay=" + maxExpiryDelay + ", defaultLastValueQueue=" + defaultLastValueQueue + ", defaultLastValueKey=" + defaultLastValueKey + ", defaultNonDestructive=" + defaultNonDestructive + ", defaultExclusiveQueue=" + defaultExclusiveQueue + ", defaultGroupRebalance=" + defaultGroupRebalance + ", defaultGroupRebalancePauseDispatch=" + defaultGroupRebalancePauseDispatch + ", defaultGroupBuckets=" + defaultGroupBuckets + ", defaultGroupFirstKey=" + defaultGroupFirstKey + ", redistributionDelay=" + redistributionDelay + ", sendToDLAOnNoRoute=" + sendToDLAOnNoRoute + ", slowConsumerThreshold=" + slowConsumerThreshold + ", slowConsumerThresholdMeasurementUnit=" + slowConsumerThresholdMeasurementUnit + ", slowConsumerCheckPeriod=" + slowConsumerCheckPeriod + ", slowConsumerPolicy=" + slowConsumerPolicy + ", autoCreateJmsQueues=" + autoCreateJmsQueues + ", autoDeleteJmsQueues=" + autoDeleteJmsQueues + ", autoCreateJmsTopics=" + autoCreateJmsTopics + ", autoDeleteJmsTopics=" + autoDeleteJmsTopics + ", autoCreateQueues=" + autoCreateQueues + ", autoDeleteQueues=" + autoDeleteQueues + ", autoDeleteCreatedQueues=" + autoDeleteCreatedQueues + ", autoDeleteQueuesDelay=" + autoDeleteQueuesDelay + ", autoDeleteQueuesSkipUsageCheck=" + autoDeleteQueuesSkipUsageCheck + ", autoDeleteQueuesMessageCount=" + autoDeleteQueuesMessageCount + ", defaultRingSize=" + defaultRingSize + ", retroactiveMessageCount=" + retroactiveMessageCount + ", configDeleteQueues=" + configDeleteQueues + ", autoCreateAddresses=" + autoCreateAddresses + ", autoDeleteAddresses=" + autoDeleteAddresses + ", autoDeleteAddressesDelay=" + autoDeleteAddressesDelay + ", autoDeleteAddressesSkipUsageCheck=" + autoDeleteAddressesSkipUsageCheck + ", configDeleteAddresses=" + configDeleteAddresses + ", configDeleteDiverts=" + configDeleteDiverts + ", managementBrowsePageSize=" + managementBrowsePageSize + ", maxSizeBytesRejectThreshold=" + maxSizeBytesRejectThreshold + ", defaultMaxConsumers=" + defaultMaxConsumers + ", defaultPurgeOnNoConsumers=" + defaultPurgeOnNoConsumers + ", defaultConsumersBeforeDispatch=" + defaultConsumersBeforeDispatch + ", defaultDelayBeforeDispatch=" + defaultDelayBeforeDispatch + ", defaultQueueRoutingType=" + defaultQueueRoutingType + ", defaultAddressRoutingType=" + defaultAddressRoutingType + ", defaultConsumerWindowSize=" + defaultConsumerWindowSize + ", autoCreateDeadLetterResources=" + autoCreateDeadLetterResources + ", deadLetterQueuePrefix=" + deadLetterQueuePrefix + ", deadLetterQueueSuffix=" + deadLetterQueueSuffix + ", autoCreateExpiryResources=" + autoCreateExpiryResources + ", expiryQueuePrefix=" + expiryQueuePrefix + ", expiryQueueSuffix=" + expiryQueueSuffix + ", enableMetrics=" + enableMetrics + ", managementMessageAttributeSizeLimit=" + managementMessageAttributeSizeLimit + ", enableIngressTimestamp=" + enableIngressTimestamp + ", idCacheSize=" + idCacheSize + ", queuePrefetch=" + queuePrefetch + '}';
return "AddressSettings{" + "addressFullMessagePolicy=" + addressFullMessagePolicy + ", maxSizeBytes=" + maxSizeBytes + ", maxReadPageBytes=" + maxReadPageBytes + ", maxReadPageMessages=" + maxReadPageMessages + ", prefetchPageBytes=" + prefetchPageBytes + ", prefetchPageMessages=" + prefetchPageMessages + ", pageLimitBytes=" + pageLimitBytes + ", pageLimitMessages=" + pageLimitMessages + ", pageFullMessagePolicy=" + pageFullMessagePolicy + ", maxSizeMessages=" + maxSizeMessages + ", pageSizeBytes=" + pageSizeBytes + ", pageMaxCache=" + pageCacheMaxSize + ", dropMessagesWhenFull=" + dropMessagesWhenFull + ", maxDeliveryAttempts=" + maxDeliveryAttempts + ", messageCounterHistoryDayLimit=" + messageCounterHistoryDayLimit + ", redeliveryDelay=" + redeliveryDelay + ", redeliveryMultiplier=" + redeliveryMultiplier + ", redeliveryCollisionAvoidanceFactor=" + redeliveryCollisionAvoidanceFactor + ", maxRedeliveryDelay=" + maxRedeliveryDelay + ", deadLetterAddress=" + deadLetterAddress + ", expiryAddress=" + expiryAddress + ", expiryDelay=" + expiryDelay + ", minExpiryDelay=" + minExpiryDelay + ", maxExpiryDelay=" + maxExpiryDelay + ", defaultLastValueQueue=" + defaultLastValueQueue + ", defaultLastValueKey=" + defaultLastValueKey + ", defaultNonDestructive=" + defaultNonDestructive + ", defaultExclusiveQueue=" + defaultExclusiveQueue + ", defaultGroupRebalance=" + defaultGroupRebalance + ", defaultGroupRebalancePauseDispatch=" + defaultGroupRebalancePauseDispatch + ", defaultGroupBuckets=" + defaultGroupBuckets + ", defaultGroupFirstKey=" + defaultGroupFirstKey + ", redistributionDelay=" + redistributionDelay + ", sendToDLAOnNoRoute=" + sendToDLAOnNoRoute + ", slowConsumerThreshold=" + slowConsumerThreshold + ", slowConsumerThresholdMeasurementUnit=" + slowConsumerThresholdMeasurementUnit + ", slowConsumerCheckPeriod=" + slowConsumerCheckPeriod + ", slowConsumerPolicy=" + slowConsumerPolicy + ", autoCreateJmsQueues=" + autoCreateJmsQueues + ", autoDeleteJmsQueues=" + autoDeleteJmsQueues + ", autoCreateJmsTopics=" + autoCreateJmsTopics + ", autoDeleteJmsTopics=" + autoDeleteJmsTopics + ", autoCreateQueues=" + autoCreateQueues + ", autoDeleteQueues=" + autoDeleteQueues + ", autoDeleteCreatedQueues=" + autoDeleteCreatedQueues + ", autoDeleteQueuesDelay=" + autoDeleteQueuesDelay + ", autoDeleteQueuesSkipUsageCheck=" + autoDeleteQueuesSkipUsageCheck + ", autoDeleteQueuesMessageCount=" + autoDeleteQueuesMessageCount + ", defaultRingSize=" + defaultRingSize + ", retroactiveMessageCount=" + retroactiveMessageCount + ", configDeleteQueues=" + configDeleteQueues + ", autoCreateAddresses=" + autoCreateAddresses + ", autoDeleteAddresses=" + autoDeleteAddresses + ", autoDeleteAddressesDelay=" + autoDeleteAddressesDelay + ", autoDeleteAddressesSkipUsageCheck=" + autoDeleteAddressesSkipUsageCheck + ", configDeleteAddresses=" + configDeleteAddresses + ", configDeleteDiverts=" + configDeleteDiverts + ", managementBrowsePageSize=" + managementBrowsePageSize + ", maxSizeBytesRejectThreshold=" + maxSizeBytesRejectThreshold + ", defaultMaxConsumers=" + defaultMaxConsumers + ", defaultPurgeOnNoConsumers=" + defaultPurgeOnNoConsumers + ", defaultConsumersBeforeDispatch=" + defaultConsumersBeforeDispatch + ", defaultDelayBeforeDispatch=" + defaultDelayBeforeDispatch + ", defaultQueueRoutingType=" + defaultQueueRoutingType + ", defaultAddressRoutingType=" + defaultAddressRoutingType + ", defaultConsumerWindowSize=" + defaultConsumerWindowSize + ", autoCreateDeadLetterResources=" + autoCreateDeadLetterResources + ", deadLetterQueuePrefix=" + deadLetterQueuePrefix + ", deadLetterQueueSuffix=" + deadLetterQueueSuffix + ", autoCreateExpiryResources=" + autoCreateExpiryResources + ", expiryQueuePrefix=" + expiryQueuePrefix + ", expiryQueueSuffix=" + expiryQueueSuffix + ", enableMetrics=" + enableMetrics + ", managementMessageAttributeSizeLimit=" + managementMessageAttributeSizeLimit + ", enableIngressTimestamp=" + enableIngressTimestamp + ", idCacheSize=" + idCacheSize + ", queuePrefetch=" + queuePrefetch + ", initialQueueBufferSize=" + initialQueueBufferSize
+ '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4465,6 +4465,15 @@
</xsd:annotation>
</xsd:element>

<xsd:element name="initial-queue-buffer-size" default="8192" type="xsd:int" maxOccurs="1" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
This will set the initial intermediate message reference buffer size for all queues on the matching address. Will use the
default initial size if not configured.
</xsd:documentation>
</xsd:annotation>
</xsd:element>

</xsd:all>

<xsd:attribute name="match" type="xsd:string" use="required">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ public void testFileConfiguration() {
assertTrue(conf.getAddressSettings().get("a1").isEnableMetrics());
assertTrue(conf.getAddressSettings().get("a1").isEnableIngressTimestamp());
assertNull(conf.getAddressSettings().get("a1").getIDCacheSize());
assertNull(conf.getAddressSettings().get("a1").getInitialQueueBufferSize());

assertEquals("a2.1", conf.getAddressSettings().get("a2").getDeadLetterAddress().toString());
assertTrue(conf.getAddressSettings().get("a2").isAutoCreateDeadLetterResources());
Expand Down Expand Up @@ -575,6 +576,7 @@ public void testFileConfiguration() {
assertFalse(conf.getAddressSettings().get("a2").isEnableMetrics());
assertFalse(conf.getAddressSettings().get("a2").isEnableIngressTimestamp());
assertEquals(Integer.valueOf(500), conf.getAddressSettings().get("a2").getIDCacheSize());
assertEquals(Integer.valueOf(128), conf.getAddressSettings().get("a2").getInitialQueueBufferSize());

assertEquals(111, conf.getMirrorAckManagerQueueAttempts());
assertEquals(222, conf.getMirrorAckManagerPageAttempts());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,16 @@ public void testTWO_CHARACTERS() {
ValidatorsTest.success(Validators.NULL_OR_TWO_CHARACTERS, null);
}

@Test
public void testPOSITIVE_POWER_OF_TWO() {
ValidatorsTest.failure(Validators.POSITIVE_POWER_OF_TWO, 0);
ValidatorsTest.failure(Validators.POSITIVE_POWER_OF_TWO, -10);
ValidatorsTest.failure(Validators.POSITIVE_POWER_OF_TWO, 127);

ValidatorsTest.success(Validators.POSITIVE_POWER_OF_TWO, 2);
ValidatorsTest.success(Validators.POSITIVE_POWER_OF_TWO, 64);
ValidatorsTest.success(Validators.POSITIVE_POWER_OF_TWO, 1024);
ValidatorsTest.success(Validators.POSITIVE_POWER_OF_TWO, 16777216);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,11 @@ public long getRingSize() {
return 0;
}

@Override
public int getInitialQueueBufferSize() {
return 0;
}

@Override
public ReferenceCounter getConsumersRefCount() {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1717,5 +1717,10 @@ public boolean isExclusive() {
public void setExclusive(boolean exclusive) {

}

@Override
public int getInitialQueueBufferSize() {
return 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ private void testSingleMerge(boolean copy) {
addressSettingsToMerge.setMinExpiryDelay(888L);
addressSettingsToMerge.setMaxExpiryDelay(777L);
addressSettingsToMerge.setIDCacheSize(5);
addressSettingsToMerge.setInitialQueueBufferSize(256);

if (copy) {
addressSettings = addressSettings.mergeCopy(addressSettingsToMerge);
Expand All @@ -113,6 +114,7 @@ private void testSingleMerge(boolean copy) {
assertEquals(Long.valueOf(888), addressSettings.getMinExpiryDelay());
assertEquals(Long.valueOf(777), addressSettings.getMaxExpiryDelay());
assertEquals(Integer.valueOf(5), addressSettings.getIDCacheSize());
assertEquals(Integer.valueOf(256), addressSettings.getInitialQueueBufferSize());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@
<management-browse-page-size>400</management-browse-page-size>
<management-message-attribute-size-limit>265</management-message-attribute-size-limit>
<id-cache-size>500</id-cache-size>
<initial-queue-buffer-size>128</initial-queue-buffer-size>
</address-setting>
</address-settings>
<resource-limit-settings>
Expand Down
Loading

0 comments on commit efa781b

Please sign in to comment.