Skip to content

Conversation

@djelinski
Copy link
Member

@djelinski djelinski commented Nov 7, 2025

CUBIC is a standard TCP congestion control algorithm that uses a cubic function instead of a linear congestion window increase function to improve scalability and stability over fast and long-distance networks. CUBIC has been adopted as the default TCP congestion control algorithm by the Linux, Windows, and Apple stacks.

This PR adds a new congestion controller algorithm. It reuses a large part of the QuicRenoCongestionController, which was refactored to two classes - QuicBaseCongestionController, containing the shared code, and QuicRenoCongestionController, containing only the code that is unique to Reno.

CUBIC is now the default congestion controller. Reno can still be selected by setting the system property jdk.httpclient.quic.congestionController to reno.

A new test was added to exercise the new congestion controller. Existing tests continue to pass.


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Integration blocker

 ⚠️ Dependency #28156 must be integrated first

Issue

  • JDK-8371475: HttpClient: Implement CUBIC congestion controller (Enhancement - P4)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/28195/head:pull/28195
$ git checkout pull/28195

Update a local copy of the PR:
$ git checkout pull/28195
$ git pull https://git.openjdk.org/jdk.git pull/28195/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 28195

View PR using the GUI difftool:
$ git pr show -t 28195

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/28195.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Nov 7, 2025

👋 Welcome back djelinski! A progress list of the required criteria for merging this PR into pr/28156 will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Nov 7, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk openjdk bot changed the title 8371475 8371475: HttpClient: Implement CUBIC congestion controller Nov 7, 2025
@openjdk openjdk bot added the net net-dev@openjdk.org label Nov 7, 2025
@openjdk
Copy link

openjdk bot commented Nov 7, 2025

@djelinski The following label will be automatically applied to this pull request:

  • net

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@djelinski djelinski marked this pull request as ready for review November 7, 2025 13:56
@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 7, 2025
@mlbridge
Copy link

mlbridge bot commented Nov 7, 2025

Webrevs

@AlanBateman
Copy link
Contributor

If jdk.httpclient.quic.congestionController is exposed then we'll need to track this with a CSR.

Copy link
Contributor

@vy vy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really neat work @djelinski! I liked the surgery you carried out in QuicBaseCC. 💯

I've dropped some minor remarks. I guess we will need some time to wrap our mind around the math involved in the PR.


private final QuicPacer pacer;

class QuicRenoCongestionController extends QuicBaseCongestionController {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess thins can be final and consequently protected modifier can be removed from the implemented methods.

Comment on lines +46 to +47
boolean isAppLimited;
isAppLimited = congestionWindow > maxBytesInFlight + 2L * maxDatagramSize;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
boolean isAppLimited;
isAppLimited = congestionWindow > maxBytesInFlight + 2L * maxDatagramSize;
boolean isAppLimited = congestionWindow > maxBytesInFlight + 2L * maxDatagramSize;

@djelinski, I see you verbatim copied these lines – which is fine, and makes things easier to review. Nevertheless, I want to double-check: do we need to guard against any arithmetic overflows here?

* @spec https://www.rfc-editor.org/rfc/rfc9438.html
* RFC 9438: CUBIC for Fast and Long-Distance Networks
*/
public class QuicCubicCongestionController extends QuicBaseCongestionController {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this can be final.

Comment on lines +61 to +62
super(dbgTag, rttEstimator);
this.rttEstimator = rttEstimator;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make rttEstimator a protected field of QuicBaseCongestionController?

Comment on lines +121 to +122
// this is less aggressive than RFC 9438, which uses target=Wcubic(t+RTT),
// but seems to work well enough
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we also document why we deviate from the RFC?

Comment on lines +111 to +112
boolean isAppLimited;
isAppLimited = sentTime.isAfter(lastFullWindow);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
boolean isAppLimited;
isAppLimited = sentTime.isAfter(lastFullWindow);
boolean isAppLimited = sentTime.isAfter(lastFullWindow);


/*
* @test
* @run testng/othervm -Djdk.httpclient.HttpClient.log=trace,quic:cc CubicTest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we use JUnit instead?


private static QuicCongestionController createCongestionController
(String dbgTag, QuicRttEstimator rttEstimator) {
String algo = System.getProperty("jdk.httpclient.quic.congestionController", "cubic");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep this internal? That is, can we use jdk.internal.httpclient.quic.congestionController instead?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

net net-dev@openjdk.org rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

3 participants