Skip to content

Commit

Permalink
performance improve
Browse files Browse the repository at this point in the history
  • Loading branch information
huangyuanbing committed Feb 6, 2024
1 parent 031f6f1 commit 8ace819
Show file tree
Hide file tree
Showing 51 changed files with 524 additions and 522 deletions.
2 changes: 1 addition & 1 deletion quiche/quic/core/congestion_control/bbr2_misc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ void Bbr2NetworkModel::AdaptLowerBounds(
case Bbr2Params::INFLIGHT_REDUCTION: {
// Use a max of BDP and inflight to avoid starving app-limited flows.
const QuicByteCount effective_inflight =
std::max(BDP(), congestion_event.prior_bytes_in_flight);
std::max(BDP(), (QuicByteCount)congestion_event.prior_bytes_in_flight);
// This could use bytes_lost_in_round if the bandwidth_lo_ was saved
// when entering 'recovery', but this BBRv2 implementation doesn't have
// recovery defined.
Expand Down
24 changes: 13 additions & 11 deletions quiche/quic/core/congestion_control/bbr2_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {
*/

// The gain for CWND in startup.
float startup_cwnd_gain = 2.0;
float startup_cwnd_gain = 2.0f;
// TODO(wub): Maybe change to the newly derived value of 2.773 (4 * ln(2)).
float startup_pacing_gain = 2.885;
float startup_pacing_gain = 2.885f;

// STARTUP or PROBE_UP are exited if the total bandwidth growth is less than
// |full_bw_threshold| in the last |startup_full_bw_rounds| round trips.
float full_bw_threshold = 1.25;
float full_bw_threshold = 1.25f;

QuicRoundTripCount startup_full_bw_rounds = 3;

Expand All @@ -107,8 +107,8 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {
/*
* DRAIN parameters.
*/
float drain_cwnd_gain = 2.0;
float drain_pacing_gain = 1.0 / 2.885;
float drain_cwnd_gain = 2.0f;
float drain_pacing_gain = 1.0f / 2.885f;

/*
* PROBE_BW parameters.
Expand Down Expand Up @@ -180,7 +180,7 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {

// A common factor for multiplicative decreases. Used for adjusting
// bandwidth_lo, inflight_lo and inflight_hi upon losses.
float beta = 0.3;
float beta = 0.3f;

Limits<QuicByteCount> cwnd_limits;

Expand Down Expand Up @@ -296,19 +296,19 @@ struct QUIC_EXPORT_PRIVATE Bbr2CongestionEvent {
QuicTime event_time = QuicTime::Zero();

// The congestion window prior to the processing of the ack/loss events.
QuicByteCount prior_cwnd;
QuicStreamCount prior_cwnd;

// Total bytes inflight before the processing of the ack/loss events.
QuicByteCount prior_bytes_in_flight = 0;
QuicStreamCount prior_bytes_in_flight = 0;

// Total bytes inflight after the processing of the ack/loss events.
QuicByteCount bytes_in_flight = 0;
QuicStreamCount bytes_in_flight = 0;

// Total bytes acked from acks in this event.
QuicByteCount bytes_acked = 0;
QuicStreamCount bytes_acked = 0;

// Total bytes lost from losses in this event.
QuicByteCount bytes_lost = 0;
QuicStreamCount bytes_lost = 0;

// Whether acked_packets indicates the end of a round trip.
bool end_of_round_trip = false;
Expand Down Expand Up @@ -366,6 +366,8 @@ class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {

void OnApplicationLimited() { bandwidth_sampler_.OnAppLimited(); }

float GetLossRate() const { return 1.0 * bandwidth_sampler_.total_bytes_lost() / bandwidth_sampler_.total_bytes_sent(); }

// Calculates BDP using the current MaxBandwidth.
QuicByteCount BDP() const { return BDP(MaxBandwidth()); }

Expand Down
14 changes: 8 additions & 6 deletions quiche/quic/core/congestion_control/bbr2_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ namespace {
// Constants based on TCP defaults.
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
// Does not inflate the pacing rate.
const QuicByteCount kDefaultMinimumCongestionWindow = 4 * kMaxSegmentSize;
constexpr QuicByteCount kDefaultMinimumCongestionWindow = 4 * kMaxSegmentSize;

const float kInitialPacingGain = 2.885f;
constexpr float kInitialPacingGain = 2.885f;

const int kMaxModeChangesPerCongestionEvent = 4;
constexpr int kMaxModeChangesPerCongestionEvent = 4;
} // namespace

// Call |member_function_call| based on the current Bbr2Mode we are in. e.g.
Expand Down Expand Up @@ -261,7 +261,7 @@ void Bbr2Sender::AdjustNetworkParameters(const NetworkParams& params) {
}

pacing_rate_ = std::max(pacing_rate_, QuicBandwidth::FromBytesAndTimeDelta(
cwnd_, model_.MinRtt()));
GetCongestionWindow(), model_.MinRtt()));
}
}

Expand Down Expand Up @@ -375,7 +375,7 @@ void Bbr2Sender::UpdatePacingRate(QuicByteCount bytes_acked) {

if (model_.total_bytes_acked() == bytes_acked) {
// After the first ACK, cwnd_ is still the initial congestion window.
pacing_rate_ = QuicBandwidth::FromBytesAndTimeDelta(cwnd_, model_.MinRtt());
pacing_rate_ = QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), model_.MinRtt());
return;
}

Expand Down Expand Up @@ -461,6 +461,7 @@ void Bbr2Sender::OnPacketNeutered(QuicPacketNumber packet_number) {
}

bool Bbr2Sender::CanSend(QuicByteCount bytes_in_flight) {
//float loss_rate = 1 - (2.0 * connection_stats_->packets_lost) / (connection_stats_->packets_sent + 1);
const bool result = bytes_in_flight < GetCongestionWindow();
return result;
}
Expand All @@ -471,7 +472,8 @@ QuicByteCount Bbr2Sender::GetCongestionWindow() const {
}

QuicBandwidth Bbr2Sender::PacingRate(QuicByteCount /*bytes_in_flight*/) const {
return pacing_rate_;
const float loss_rate = 1 - 3.0 * connection_stats_->packets_lost / (1000 + connection_stats_->packets_sent); //* model_.GetLossRate();
return pacing_rate_ * loss_rate;
}

void Bbr2Sender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
Expand Down
2 changes: 1 addition & 1 deletion quiche/quic/core/congestion_control/bbr2_startup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Bbr2Mode Bbr2StartupMode::OnCongestionEvent(
const LostPacketVector& /*lost_packets*/,
const Bbr2CongestionEvent& congestion_event) {
if (model_->full_bandwidth_reached()) {
QUIC_BUG(11211) << "In STARTUP, but full_bandwidth_reached is true.";
QUIC_BUG() << "In STARTUP, but full_bandwidth_reached is true.";
return Bbr2Mode::DRAIN;
}
if (!congestion_event.end_of_round_trip) {
Expand Down
24 changes: 12 additions & 12 deletions quiche/quic/core/congestion_control/bbr_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,31 @@ namespace {
// Constants based on TCP defaults.
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
// Does not inflate the pacing rate.
const QuicByteCount kDefaultMinimumCongestionWindow = 4 * kMaxSegmentSize;
constexpr QuicByteCount kDefaultMinimumCongestionWindow = 4 * kMaxSegmentSize;

// The gain used for the STARTUP, equal to 2/ln(2).
const float kDefaultHighGain = 2.885f;
constexpr float kDefaultHighGain = 2.885f;
// The newly derived gain for STARTUP, equal to 4 * ln(2)
const float kDerivedHighGain = 2.773f;
constexpr float kDerivedHighGain = 2.773f;
// The newly derived CWND gain for STARTUP, 2.
const float kDerivedHighCWNDGain = 2.0f;
constexpr float kDerivedHighCWNDGain = 2.0f;
// The cycle of gains used during the PROBE_BW stage.
const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1};
constexpr float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1};

// The length of the gain cycle.
const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]);
constexpr size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]);
// The size of the bandwidth filter window, in round-trips.
const QuicRoundTripCount kBandwidthWindowSize = kGainCycleLength + 2;
constexpr QuicRoundTripCount kBandwidthWindowSize = kGainCycleLength + 2;

// The time after which the current min_rtt value expires.
const QuicTime::Delta kMinRttExpiry = QuicTime::Delta::FromSeconds(5);
constexpr QuicTime::Delta kMinRttExpiry = QuicTime::Delta::FromSeconds(5);
// The minimum time the connection can spend in PROBE_RTT mode.
const QuicTime::Delta kProbeRttTime = QuicTime::Delta::FromMilliseconds(200);
constexpr QuicTime::Delta kProbeRttTime = QuicTime::Delta::FromMilliseconds(200);
// If the bandwidth does not increase by the factor of |kStartupGrowthTarget|
// within |kRoundTripsWithoutGrowthBeforeExitingStartup| rounds, the connection
// will exit the STARTUP mode.
const float kStartupGrowthTarget = 1.25;
const QuicRoundTripCount kRoundTripsWithoutGrowthBeforeExitingStartup = 3;
constexpr float kStartupGrowthTarget = 1.25;
constexpr QuicRoundTripCount kRoundTripsWithoutGrowthBeforeExitingStartup = 3;
} // namespace

BbrSender::DebugState::DebugState(const BbrSender& sender)
Expand Down Expand Up @@ -151,7 +151,7 @@ void BbrSender::OnPacketSent(QuicTime sent_time, QuicByteCount bytes_in_flight,
QuicPacketNumber packet_number,
QuicByteCount bytes,
HasRetransmittableData is_retransmittable) {
if (stats_ && InSlowStart()) {
if (InSlowStart()) {
++stats_->slowstart_packets_sent;
stats_->slowstart_bytes_sent += bytes;
}
Expand Down
10 changes: 5 additions & 5 deletions quiche/quic/core/congestion_control/cubic_bytes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ namespace {
// Constants based on TCP defaults.
// The following constants are in 2^10 fractions of a second instead of ms to
// allow a 10 shift right to divide.
const int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3)
constexpr int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3)
// where 0.100 is 100 ms which is the scaling
// round trip time.
const int kCubeCongestionWindowScale = 410;
constexpr int kCubeCongestionWindowScale = 410;
// The cube factor for packets in bytes.
const uint64_t kCubeFactor =
constexpr uint64_t kCubeFactor =
(UINT64_C(1) << kCubeScale) / kCubeCongestionWindowScale / kDefaultTCPMSS;

const float kDefaultCubicBackoffFactor = 0.7f; // Default Cubic backoff factor.
constexpr float kDefaultCubicBackoffFactor = 0.7f; // Default Cubic backoff factor.
// Additional backoff factor when loss occurs in the concave part of the Cubic
// curve. This additional backoff factor is expected to give up bandwidth to
// new concurrent flows and speed up convergence.
const float kBetaLastMax = 0.85f;
constexpr float kBetaLastMax = 0.85f;

} // namespace

Expand Down
10 changes: 5 additions & 5 deletions quiche/quic/core/congestion_control/hybrid_slow_start.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ namespace quic {

// Note(pwestin): the magic clamping numbers come from the original code in
// tcp_cubic.c.
const int64_t kHybridStartLowWindow = 16;
constexpr int64_t kHybridStartLowWindow = 16;
// Number of delay samples for detecting the increase of delay.
const uint32_t kHybridStartMinSamples = 8;
constexpr uint32_t kHybridStartMinSamples = 8;
// Exit slow start if the min rtt has increased by more than 1/8th.
const int kHybridStartDelayFactorExp = 3; // 2^3 = 8
constexpr int kHybridStartDelayFactorExp = 3; // 2^3 = 8
// The original paper specifies 2 and 8ms, but those have changed over time.
const int64_t kHybridStartDelayMinThresholdUs = 4000;
const int64_t kHybridStartDelayMaxThresholdUs = 16000;
constexpr int64_t kHybridStartDelayMinThresholdUs = 4000;
constexpr int64_t kHybridStartDelayMaxThresholdUs = 16000;

HybridSlowStart::HybridSlowStart()
: started_(false),
Expand Down
91 changes: 52 additions & 39 deletions quiche/quic/core/congestion_control/pacing_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace {

// Configured maximum size of the burst coming out of quiescence. The burst
// is never larger than the current CWND in packets.
static const uint32_t kInitialUnpacedBurst = 10;
constexpr uint32_t kInitialUnpacedBurst = 10;

} // namespace

Expand All @@ -25,7 +25,7 @@ PacingSender::PacingSender()
ideal_next_packet_send_time_(QuicTime::Zero()),
initial_burst_size_(kInitialUnpacedBurst),
lumpy_tokens_(0),
alarm_granularity_(kAlarmGranularity),
alarm_granularity_(kAlarmGranularity * 2),
pacing_limited_(false) {}

PacingSender::~PacingSender() {}
Expand Down Expand Up @@ -54,47 +54,53 @@ void PacingSender::OnPacketSent(
QuicPacketNumber packet_number, QuicByteCount bytes,
HasRetransmittableData has_retransmittable_data) {
QUICHE_DCHECK(sender_ != nullptr);
QUIC_DVLOG(3) << "Packet " << packet_number << " with " << bytes
<< " bytes sent at " << sent_time
<< ". bytes_in_flight: " << bytes_in_flight;
sender_->OnPacketSent(sent_time, bytes_in_flight, packet_number, bytes,
has_retransmittable_data);
if (has_retransmittable_data != HAS_RETRANSMITTABLE_DATA) {
return;
}
// If in recovery, the connection is not coming out of quiescence.
if (bytes_in_flight == 0 && !sender_->InRecovery()) {
// Add more burst tokens anytime the connection is leaving quiescence, but
// limit it to the equivalent of a single bulk write, not exceeding the
// current CWND in packets.
burst_tokens_ = std::min(
initial_burst_size_,
static_cast<uint32_t>(sender_->GetCongestionWindow() / kDefaultTCPMSS));

if (remove_non_initial_burst_) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_pacing_remove_non_initial_burst, 1, 2);
}
if (burst_tokens_ > 0) {
--burst_tokens_;
ideal_next_packet_send_time_ = QuicTime::Zero();
pacing_limited_ = false;
return;
else {
// If in recovery, the connection is not coming out of quiescence.
if (bytes_in_flight == 0 && !sender_->InRecovery()) {
// Add more burst tokens anytime the connection is leaving quiescence, but
// limit it to the equivalent of a single bulk write, not exceeding the
// current CWND in packets.
burst_tokens_ = std::min(initial_burst_size_,
static_cast<uint32_t>(sender_->GetCongestionWindow() / kDefaultTCPMSS));
if (burst_tokens_ > 0) {
--burst_tokens_;
ideal_next_packet_send_time_ = QuicTime::Zero();
pacing_limited_ = false;
return;
}
}
}

// The next packet should be sent as soon as the current packet has been
// transferred. PacingRate is based on bytes in flight including this packet.
QuicTime::Delta delay =
PacingRate(bytes_in_flight + bytes).TransferTime(bytes);
if (!pacing_limited_ || lumpy_tokens_ == 0) {
// Reset lumpy_tokens_ if either application or cwnd throttles sending or
// token runs out.
lumpy_tokens_ = std::max(
1u, std::min(static_cast<uint32_t>(GetQuicFlag(quic_lumpy_pacing_size)),
static_cast<uint32_t>(
(sender_->GetCongestionWindow() *
GetQuicFlag(quic_lumpy_pacing_cwnd_fraction)) /
kDefaultTCPMSS)));
lumpy_tokens_ = //std::max(1u,
std::min(static_cast<uint32_t>(GetQuicFlag(quic_lumpy_pacing_size)),
uint32_t(sender_->GetCongestionWindow() / (kDefaultTCPMSS * 4)));
if (sender_->BandwidthEstimate() <
QuicBandwidth::FromKBitsPerSecond(
GetQuicFlag(quic_lumpy_pacing_min_bandwidth_kbps))) {
// Below 1.2Mbps, send 1 packet at once, because one full-sized packet
// is about 10ms of queueing.
lumpy_tokens_ = 1u;
}
if ((bytes_in_flight + bytes) >= sender_->GetCongestionWindow()) {
else if ((bytes_in_flight + bytes) >= sender_->GetCongestionWindow()) {
// Don't add lumpy_tokens if the congestion controller is CWND limited.
lumpy_tokens_ = 1u;
}
Expand Down Expand Up @@ -129,32 +135,39 @@ QuicTime::Delta PacingSender::TimeUntilSend(

if (!sender_->CanSend(bytes_in_flight)) {
// The underlying sender prevents sending.
return QuicTime::Delta::Infinite();
//return QuicTime::Delta::FromSeconds(1);
return PacingRate(bytes_in_flight).TransferTime(bytes_in_flight - sender_->GetCongestionWindow());
}

if ((lumpy_tokens_ | burst_tokens_) > 0 || bytes_in_flight == 0) {
// Don't pace if we have burst tokens available or leaving quiescence.
QUIC_DVLOG(1) << "Sending packet now. burst_tokens:" << burst_tokens_
<< ", bytes_in_flight:" << bytes_in_flight
<< ", lumpy_tokens:" << lumpy_tokens_;
return QuicTime::Delta::Zero();
if (remove_non_initial_burst_) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_pacing_remove_non_initial_burst, 2, 2);
if (burst_tokens_ | lumpy_tokens_) {
// Don't pace if we have burst or lumpy tokens available.
QUIC_DVLOG(1) << "Can send packet now. burst_tokens:" << burst_tokens_
<< ", lumpy_tokens:" << lumpy_tokens_;
return QuicTime::Delta::Zero();
}
} else {
if (burst_tokens_ > 0 || bytes_in_flight == 0 || lumpy_tokens_ > 0) {
// Don't pace if we have burst tokens available or leaving quiescence.
QUIC_DVLOG(1) << "Sending packet now. burst_tokens:" << burst_tokens_
<< ", bytes_in_flight:" << bytes_in_flight
<< ", lumpy_tokens:" << lumpy_tokens_;
return QuicTime::Delta::Zero();
}
}

const auto delay = ideal_next_packet_send_time_ - now;
// If the next send time is within the alarm granularity, send immediately.
if (ideal_next_packet_send_time_ > now + alarm_granularity_) {
QUIC_DVLOG(1) << "Delaying packet: "
<< (ideal_next_packet_send_time_ - now).ToMicroseconds();
return ideal_next_packet_send_time_ - now;
if (false && delay.ToMicroseconds() < 0) {
QUIC_DVLOG(1) << "Delaying packet: " << delay.ToMicroseconds();
}

QUIC_DVLOG(1) << "Sending packet now. ideal_next_packet_send_time: "
<< ideal_next_packet_send_time_ << ", now: " << now;
return QuicTime::Delta::Zero();
return delay;
}

QuicBandwidth PacingSender::PacingRate(QuicByteCount bytes_in_flight) const {
QUICHE_DCHECK(sender_ != nullptr);
if (!max_pacing_rate_.IsZero()) {
QUICHE_DCHECK(sender_ != nullptr && max_pacing_rate_.IsZero());
if (false && !max_pacing_rate_.IsZero()) {
return QuicBandwidth::FromBitsPerSecond(
std::min(max_pacing_rate_.ToBitsPerSecond(),
sender_->PacingRate(bytes_in_flight).ToBitsPerSecond()));
Expand Down
Loading

0 comments on commit 8ace819

Please sign in to comment.