Skip to content

Commit 4dea3f7

Browse files
authored
Avoid using JVM HashCode on Http 2 DefaultStream (#13760)
Motivation: relying on DefaultStream's hashCode forces calling into JVM's strategy for identity hash code Modifications: Use the stream's id to identify DefaultStream Result: Faster active stream insertion, saving producing JVM's hashcode
1 parent 3b81f2c commit 4dea3f7

1 file changed

Lines changed: 29 additions & 4 deletions

File tree

codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Connection.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,13 @@ private class DefaultStream implements Http2Stream {
388388
private static final byte META_STATE_RECV_HEADERS = 1 << 4;
389389
private static final byte META_STATE_RECV_TRAILERS = 1 << 5;
390390
private final int id;
391+
private final long identity;
391392
private final PropertyMap properties = new PropertyMap();
392393
private State state;
393394
private byte metaState;
394395

395-
DefaultStream(int id, State state) {
396+
DefaultStream(long identity, int id, State state) {
397+
this.identity = identity;
396398
this.id = id;
397399
this.state = state;
398400
}
@@ -599,14 +601,28 @@ void resizeIfNecessary(int index) {
599601
}
600602
}
601603
}
604+
605+
@Override
606+
public boolean equals(final Object obj) {
607+
return super.equals(obj);
608+
}
609+
610+
@Override
611+
public int hashCode() {
612+
long value = identity;
613+
if (value == 0) {
614+
return System.identityHashCode(this);
615+
}
616+
return (int) (value ^ (value >>> 32));
617+
}
602618
}
603619

604620
/**
605621
* Stream class representing the connection, itself.
606622
*/
607623
private final class ConnectionStream extends DefaultStream {
608624
ConnectionStream() {
609-
super(CONNECTION_STREAM_ID, IDLE);
625+
super(0, CONNECTION_STREAM_ID, IDLE);
610626
}
611627

612628
@Override
@@ -670,6 +686,10 @@ public boolean isPushPromiseSent() {
670686
*/
671687
private final class DefaultEndpoint<F extends Http2FlowController> implements Endpoint<F> {
672688
private final boolean server;
689+
/**
690+
* This is an always increasing sequence number used to hash {@link DefaultStream} instances.
691+
*/
692+
private long lastCreatedStreamIdentity;
673693
/**
674694
* The minimum stream ID allowed when creating the next stream. This only applies at the time the stream is
675695
* created. If the ID of the stream being created is less than this value, stream creation will fail. Upon
@@ -694,6 +714,7 @@ private final class DefaultEndpoint<F extends Http2FlowController> implements En
694714
int numStreams;
695715

696716
DefaultEndpoint(boolean server, int maxReservedStreams) {
717+
this.lastCreatedStreamIdentity = 0;
697718
this.server = server;
698719

699720
// Determine the starting stream ID for this endpoint. Client-initiated streams
@@ -750,8 +771,10 @@ public DefaultStream createStream(int streamId, boolean halfClosed) throws Http2
750771

751772
checkNewStreamAllowed(streamId, state);
752773

774+
lastCreatedStreamIdentity++;
775+
753776
// Create and initialize the stream.
754-
DefaultStream stream = new DefaultStream(streamId, state);
777+
DefaultStream stream = new DefaultStream(lastCreatedStreamIdentity, streamId, state);
755778

756779
incrementExpectedStreamId(streamId);
757780

@@ -785,8 +808,10 @@ public DefaultStream reservePushStream(int streamId, Http2Stream parent) throws
785808
State state = isLocal() ? RESERVED_LOCAL : RESERVED_REMOTE;
786809
checkNewStreamAllowed(streamId, state);
787810

811+
lastCreatedStreamIdentity++;
812+
788813
// Create and initialize the stream.
789-
DefaultStream stream = new DefaultStream(streamId, state);
814+
DefaultStream stream = new DefaultStream(lastCreatedStreamIdentity, streamId, state);
790815

791816
incrementExpectedStreamId(streamId);
792817

0 commit comments

Comments
 (0)