You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2020/09/30 12:46:30 UTC
[tomcat] 02/10: Reduce memory footprint of closed http/2 streams
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit e1a53fb2d567b81cfaa4fcfa94ef870f15a6e289
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Sep 24 17:32:49 2020 +0100
Reduce memory footprint of closed http/2 streams
This refactoring replaces closed streams with a new RecycledStream
object and changes the mechanism used to look up known streams.
Pull up re-prioritisation
---
.../apache/coyote/http2/AbstractNonZeroStream.java | 71 ++++++++++++++++++++++
java/org/apache/coyote/http2/AbstractStream.java | 6 +-
.../apache/coyote/http2/Http2UpgradeHandler.java | 6 +-
java/org/apache/coyote/http2/RecycledStream.java | 10 +--
java/org/apache/coyote/http2/Stream.java | 55 -----------------
5 files changed, 78 insertions(+), 70 deletions(-)
diff --git a/java/org/apache/coyote/http2/AbstractNonZeroStream.java b/java/org/apache/coyote/http2/AbstractNonZeroStream.java
index 63fb5e7..ce08cc5 100644
--- a/java/org/apache/coyote/http2/AbstractNonZeroStream.java
+++ b/java/org/apache/coyote/http2/AbstractNonZeroStream.java
@@ -16,6 +16,11 @@
*/
package org.apache.coyote.http2;
+import java.util.Iterator;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.res.StringManager;
/**
* Base class for all streams other than stream 0, the connection. Primarily
@@ -23,7 +28,73 @@ package org.apache.coyote.http2;
*/
abstract class AbstractNonZeroStream extends AbstractStream {
+ private static final Log log = LogFactory.getLog(AbstractNonZeroStream.class);
+ private static final StringManager sm = StringManager.getManager(AbstractNonZeroStream.class);
+
+ private volatile int weight;
+
+
AbstractNonZeroStream(Integer identifier) {
+ this(identifier, Constants.DEFAULT_WEIGHT);
+ }
+
+
+ AbstractNonZeroStream(Integer identifier, int weight) {
super(identifier);
+ this.weight = weight;
+ }
+
+
+ @Override
+ final int getWeight() {
+ return weight;
}
+
+
+ final void rePrioritise(AbstractStream parent, boolean exclusive, int weight) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("stream.reprioritisation.debug",
+ getConnectionId(), getIdAsString(), Boolean.toString(exclusive),
+ parent.getIdAsString(), Integer.toString(weight)));
+ }
+
+ // Check if new parent is a descendant of this stream
+ if (isDescendant(parent)) {
+ parent.detachFromParent();
+ // Cast is always safe since any descendant of this stream must be
+ // an instance of Stream
+ getParentStream().addChild((Stream) parent);
+ }
+
+ if (exclusive) {
+ // Need to move children of the new parent to be children of this
+ // stream. Slightly convoluted to avoid concurrent modification.
+ Iterator<AbstractNonZeroStream> parentsChildren = parent.getChildStreams().iterator();
+ while (parentsChildren.hasNext()) {
+ AbstractNonZeroStream parentsChild = parentsChildren.next();
+ parentsChildren.remove();
+ this.addChild(parentsChild);
+ }
+ }
+ detachFromParent();
+ parent.addChild(this);
+ this.weight = weight;
+ }
+
+
+ /*
+ * Used when removing closed streams from the tree and we know there is no
+ * need to check for circular references.
+ */
+ final void rePrioritise(AbstractStream parent, int weight) {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("stream.reprioritisation.debug",
+ getConnectionId(), getIdAsString(), Boolean.FALSE,
+ parent.getIdAsString(), Integer.toString(weight)));
+ }
+
+ parent.addChild(this);
+ this.weight = weight;
+ }
+
}
diff --git a/java/org/apache/coyote/http2/AbstractStream.java b/java/org/apache/coyote/http2/AbstractStream.java
index 21963ee..c7374b6 100644
--- a/java/org/apache/coyote/http2/AbstractStream.java
+++ b/java/org/apache/coyote/http2/AbstractStream.java
@@ -37,7 +37,7 @@ abstract class AbstractStream {
private final String idAsString;
private volatile AbstractStream parentStream = null;
- private final Set<Stream> childStreams = Collections.newSetFromMap(new ConcurrentHashMap<>());
+ private final Set<AbstractNonZeroStream> childStreams = Collections.newSetFromMap(new ConcurrentHashMap<>());
private long windowSize = ConnectionSettingsBase.DEFAULT_INITIAL_WINDOW_SIZE;
@@ -70,7 +70,7 @@ abstract class AbstractStream {
}
- final void addChild(Stream child) {
+ final void addChild(AbstractNonZeroStream child) {
child.setParentStream(this);
childStreams.add(child);
}
@@ -97,7 +97,7 @@ abstract class AbstractStream {
}
- final Set<Stream> getChildStreams() {
+ final Set<AbstractNonZeroStream> getChildStreams() {
return childStreams;
}
diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
index dbd7491..ad5e0e4 100644
--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
@@ -1269,17 +1269,17 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
Stream streamToRemove = streams.remove(streamIdToRemove);
// Move the removed Stream's children to the removed Stream's
// parent.
- Set<Stream> children = streamToRemove.getChildStreams();
+ Set<AbstractNonZeroStream> children = streamToRemove.getChildStreams();
if (children.size() == 1) {
// Shortcut
children.iterator().next().rePrioritise(
streamToRemove.getParentStream(), streamToRemove.getWeight());
} else {
int totalWeight = 0;
- for (Stream child : children) {
+ for (AbstractNonZeroStream child : children) {
totalWeight += child.getWeight();
}
- for (Stream child : children) {
+ for (AbstractNonZeroStream child : children) {
children.iterator().next().rePrioritise(
streamToRemove.getParentStream(),
streamToRemove.getWeight() * child.getWeight() / totalWeight);
diff --git a/java/org/apache/coyote/http2/RecycledStream.java b/java/org/apache/coyote/http2/RecycledStream.java
index f500646..1e630df 100644
--- a/java/org/apache/coyote/http2/RecycledStream.java
+++ b/java/org/apache/coyote/http2/RecycledStream.java
@@ -23,12 +23,10 @@ package org.apache.coyote.http2;
class RecycledStream extends AbstractNonZeroStream {
private final String connectionId;
- private int weight;
RecycledStream(Stream stream) {
- super(stream.getIdentifier());
+ super(stream.getIdentifier(), stream.getWeight());
connectionId = stream.getConnectionId();
- weight = stream.getWeight();
}
@@ -36,10 +34,4 @@ class RecycledStream extends AbstractNonZeroStream {
String getConnectionId() {
return connectionId;
}
-
-
- @Override
- int getWeight() {
- return weight;
- }
}
diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java
index 56bc129..ef7ed29 100644
--- a/java/org/apache/coyote/http2/Stream.java
+++ b/java/org/apache/coyote/http2/Stream.java
@@ -23,7 +23,6 @@ import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collections;
-import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;
@@ -67,7 +66,6 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
ACK_HEADERS = response.getMimeHeaders();
}
- private volatile int weight = Constants.DEFAULT_WEIGHT;
private volatile long contentLengthReceived = 0;
private final Http2UpgradeHandler handler;
@@ -175,53 +173,6 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
- final void rePrioritise(AbstractStream parent, boolean exclusive, int weight) {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("stream.reprioritisation.debug",
- getConnectionId(), getIdAsString(), Boolean.toString(exclusive),
- parent.getIdAsString(), Integer.toString(weight)));
- }
-
- // Check if new parent is a descendant of this stream
- if (isDescendant(parent)) {
- parent.detachFromParent();
- // Cast is always safe since any descendant of this stream must be
- // an instance of Stream
- getParentStream().addChild((Stream) parent);
- }
-
- if (exclusive) {
- // Need to move children of the new parent to be children of this
- // stream. Slightly convoluted to avoid concurrent modification.
- Iterator<Stream> parentsChildren = parent.getChildStreams().iterator();
- while (parentsChildren.hasNext()) {
- Stream parentsChild = parentsChildren.next();
- parentsChildren.remove();
- this.addChild(parentsChild);
- }
- }
- detachFromParent();
- parent.addChild(this);
- this.weight = weight;
- }
-
-
- /*
- * Used when removing closed streams from the tree and we know there is no
- * need to check for circular references.
- */
- final void rePrioritise(AbstractStream parent, int weight) {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("stream.reprioritisation.debug",
- getConnectionId(), getIdAsString(), Boolean.FALSE,
- parent.getIdAsString(), Integer.toString(weight)));
- }
-
- parent.addChild(this);
- this.weight = weight;
- }
-
-
final void receiveReset(long errorCode) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("stream.reset.receive", getConnectionId(), getIdAsString(),
@@ -566,12 +517,6 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
- @Override
- final int getWeight() {
- return weight;
- }
-
-
final Request getCoyoteRequest() {
return coyoteRequest;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org