From 3a27000022c8bcf034115d91c8cd0e14b44ab0b6 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Mon, 3 May 2021 16:18:17 -0700 Subject: [PATCH 1/2] Use `UniformStreamByteDistributor` for HTTP/2 connections Motivation: HTTP/2 spec defines priorities for streams. However, in ST we do not expose API to assign priorities for streams and this features is rarely used in general. `Http2FrameCodecBuilder` creates connections with `WeightedFairQueueByteDistributor` by default that takes priorities into account. We can use `UniformStreamByteDistributor` to reduce overhead of managing HTTP/2 streams. Modifications: - Extend `Http2FrameCodecBuilder` to use `UniformStreamByteDistributor` for new `Http2Connection`(s); Result: Less CPU usage for HTTP/2 ~1-1.5% according to the benchmarks. --- gradle.properties | 2 +- .../H2ClientParentChannelInitializer.java | 5 +- .../H2ServerParentChannelInitializer.java | 5 +- .../OptimizedHttp2FrameCodecBuilder.java | 55 +++++++++++++++++++ 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/OptimizedHttp2FrameCodecBuilder.java diff --git a/gradle.properties b/gradle.properties index fc9ecc707d..a5320a717f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ group=io.servicetalk version=0.40.0-SNAPSHOT -nettyVersion=4.1.63.Final +nettyVersion=4.1.64.Final-SNAPSHOT tcnativeVersion=2.0.38.Final jsr305Version=3.0.2 diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ClientParentChannelInitializer.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ClientParentChannelInitializer.java index 2ac45c60c2..564c8fe090 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ClientParentChannelInitializer.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ClientParentChannelInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019-2020 Apple Inc. and the ServiceTalk project authors + * Copyright © 2019-2021 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,6 @@ import java.util.function.BiPredicate; import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR; -import static io.netty.handler.codec.http2.Http2FrameCodecBuilder.forClient; import static io.servicetalk.http.netty.H2ServerParentChannelInitializer.initFrameLogger; final class H2ClientParentChannelInitializer implements ChannelInitializer { @@ -41,7 +40,7 @@ final class H2ClientParentChannelInitializer implements ChannelInitializer { @Override public void init(final Channel channel) { - final Http2FrameCodecBuilder multiplexCodecBuilder = forClient() + final Http2FrameCodecBuilder multiplexCodecBuilder = new OptimizedHttp2FrameCodecBuilder(false) // We do not want close to trigger graceful closure (go away), instead when user triggers a graceful // close, we do the appropriate go away handling. .decoupleCloseAndGoAway(true) diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ServerParentChannelInitializer.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ServerParentChannelInitializer.java index f98f33dccd..aba619e6c8 100644 --- a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ServerParentChannelInitializer.java +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ServerParentChannelInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019-2020 Apple Inc. and the ServiceTalk project authors + * Copyright © 2019-2021 Apple Inc. and the ServiceTalk project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ import java.util.function.BiPredicate; import javax.annotation.Nullable; -import static io.netty.handler.codec.http2.Http2FrameCodecBuilder.forServer; import static io.servicetalk.logging.slf4j.internal.Slf4jFixedLevelLoggers.newLogger; final class H2ServerParentChannelInitializer implements ChannelInitializer { @@ -42,7 +41,7 @@ final class H2ServerParentChannelInitializer implements ChannelInitializer { @Override public void init(final Channel channel) { - final Http2FrameCodecBuilder multiplexCodecBuilder = forServer() + final Http2FrameCodecBuilder multiplexCodecBuilder = new OptimizedHttp2FrameCodecBuilder(true) // We do not want close to trigger graceful closure (go away), instead when user triggers a graceful // close, we do the appropriate go away handling. .decoupleCloseAndGoAway(true) diff --git a/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/OptimizedHttp2FrameCodecBuilder.java b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/OptimizedHttp2FrameCodecBuilder.java new file mode 100644 index 0000000000..7aa42cbc6f --- /dev/null +++ b/servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/OptimizedHttp2FrameCodecBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright © 2021 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.servicetalk.http.netty; + +import io.netty.handler.codec.http2.DefaultHttp2Connection; +import io.netty.handler.codec.http2.DefaultHttp2RemoteFlowController; +import io.netty.handler.codec.http2.Http2FrameCodec; +import io.netty.handler.codec.http2.Http2FrameCodecBuilder; +import io.netty.handler.codec.http2.Http2RemoteFlowController; +import io.netty.handler.codec.http2.UniformStreamByteDistributor; + +/** + * Optimized variant of {@link Http2FrameCodecBuilder} that allows us to use {@link UniformStreamByteDistributor} + * for {@link Http2RemoteFlowController}. + */ +final class OptimizedHttp2FrameCodecBuilder extends Http2FrameCodecBuilder { + + private final boolean server; + + /** + * Creates a new instance. + * + * @param server {@code true} if for server, {@code false} otherwise + */ + OptimizedHttp2FrameCodecBuilder(final boolean server) { + this.server = server; + } + + @Override + public boolean isServer() { + return server; + } + + @Override + public Http2FrameCodec build() { + final DefaultHttp2Connection connection = new DefaultHttp2Connection(isServer(), maxReservedStreams()); + connection.remote().flowController(new DefaultHttp2RemoteFlowController(connection, + new UniformStreamByteDistributor(connection))); + connection(connection); + return super.build(); + } +} From ecfca0b4bd1e4f1f8a16b5e433c8867d949d7116 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 02:17:21 +0000 Subject: [PATCH 2/2] Bump dawidd6/action-download-artifact from 2.14.0 to 2.26.0 Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.14.0 to 2.26.0. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/b9571484721e8187f1fd08147b497129f8972c74...5e780fc7bbd0cac69fc73271ed86edf5dcb72d67) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci-prb-reports.yml | 2 +- .github/workflows/ci-prq-reports.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-prb-reports.yml b/.github/workflows/ci-prb-reports.yml index 3264ebe0e3..86789a8685 100644 --- a/.github/workflows/ci-prb-reports.yml +++ b/.github/workflows/ci-prb-reports.yml @@ -14,7 +14,7 @@ jobs: os: [ ubuntu-latest ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@b9571484721e8187f1fd08147b497129f8972c74 + uses: dawidd6/action-download-artifact@5e780fc7bbd0cac69fc73271ed86edf5dcb72d67 with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} diff --git a/.github/workflows/ci-prq-reports.yml b/.github/workflows/ci-prq-reports.yml index 8b21e4792b..7b7b8838a0 100644 --- a/.github/workflows/ci-prq-reports.yml +++ b/.github/workflows/ci-prq-reports.yml @@ -12,7 +12,7 @@ jobs: java: [ 8, 11 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@b9571484721e8187f1fd08147b497129f8972c74 + uses: dawidd6/action-download-artifact@5e780fc7bbd0cac69fc73271ed86edf5dcb72d67 with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} @@ -35,7 +35,7 @@ jobs: java: [ 8, 11 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@b9571484721e8187f1fd08147b497129f8972c74 + uses: dawidd6/action-download-artifact@5e780fc7bbd0cac69fc73271ed86edf5dcb72d67 with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }} @@ -58,7 +58,7 @@ jobs: java: [ 8, 11 ] steps: - name: Download Artifacts - uses: dawidd6/action-download-artifact@b9571484721e8187f1fd08147b497129f8972c74 + uses: dawidd6/action-download-artifact@5e780fc7bbd0cac69fc73271ed86edf5dcb72d67 with: github_token: ${{ secrets.GITHUB_TOKEN }} workflow: ${{ github.event.workflow_run.workflow_id }}