From 13171bdba843107d85591f5a663ef0911c43f53f Mon Sep 17 00:00:00 2001 From: Sebastian Jansson Date: Tue, 3 Jul 2018 18:11:45 +0200 Subject: [PATCH] Adds debug printing for congestion controllers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are useful for plotting creating data files that can be used to visualize and debug congestion controller behavior. Bug: webrtc:9467 Change-Id: I75b03a309b4b7d562fefe82a828ae1e6a9f069c8 Reviewed-on: https://webrtc-review.googlesource.com/86126 Commit-Queue: Sebastian Jansson Reviewed-by: Björn Terelius Cr-Commit-Position: refs/heads/master@{#23822} --- modules/congestion_controller/BUILD.gn | 15 +++++ modules/congestion_controller/bbr/BUILD.gn | 12 ++++ .../bbr/bbr_network_controller.cc | 3 +- .../bbr/bbr_network_controller.h | 4 +- .../bbr/test/bbr_printer.cc | 57 ++++++++++++++++ .../bbr/test/bbr_printer.h | 49 ++++++++++++++ .../congestion_controller/goog_cc/BUILD.gn | 11 ++++ .../goog_cc/goog_cc_network_control.cc | 23 ++++++- .../goog_cc/goog_cc_network_control.h | 4 +- .../goog_cc/test/goog_cc_printer.cc | 50 ++++++++++++++ .../goog_cc/test/goog_cc_printer.h | 48 ++++++++++++++ .../test/controller_printer.cc | 66 +++++++++++++++++++ .../test/controller_printer.h | 43 ++++++++++++ 13 files changed, 380 insertions(+), 5 deletions(-) create mode 100644 modules/congestion_controller/bbr/test/bbr_printer.cc create mode 100644 modules/congestion_controller/bbr/test/bbr_printer.h create mode 100644 modules/congestion_controller/goog_cc/test/goog_cc_printer.cc create mode 100644 modules/congestion_controller/goog_cc/test/goog_cc_printer.h create mode 100644 modules/congestion_controller/test/controller_printer.cc create mode 100644 modules/congestion_controller/test/controller_printer.h diff --git a/modules/congestion_controller/BUILD.gn b/modules/congestion_controller/BUILD.gn index dc2b079c91..5d490ae8ee 100644 --- a/modules/congestion_controller/BUILD.gn +++ b/modules/congestion_controller/BUILD.gn @@ -76,6 +76,21 @@ rtc_static_library("transport_feedback") { } if (rtc_include_tests) { + rtc_source_set("test_controller_printer") { + testonly = true + sources = [ + "test/controller_printer.cc", + "test/controller_printer.h", + ] + if (!build_with_chromium && is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + deps = [ + "../../api/transport:network_control", + "../../rtc_base:checks", + ] + } rtc_source_set("congestion_controller_unittests") { testonly = true diff --git a/modules/congestion_controller/bbr/BUILD.gn b/modules/congestion_controller/bbr/BUILD.gn index c30f38a505..fdee88c37c 100644 --- a/modules/congestion_controller/bbr/BUILD.gn +++ b/modules/congestion_controller/bbr/BUILD.gn @@ -113,6 +113,18 @@ rtc_source_set("windowed_filter") { ] } if (rtc_include_tests) { + rtc_source_set("test_bbr_printer") { + testonly = true + sources = [ + "test/bbr_printer.cc", + "test/bbr_printer.h", + ] + deps = [ + ":bbr", + ":bbr_controller", + "..:test_controller_printer", + ] + } rtc_source_set("bbr_unittests") { testonly = true sources = [ diff --git a/modules/congestion_controller/bbr/bbr_network_controller.cc b/modules/congestion_controller/bbr/bbr_network_controller.cc index fd50ff0805..890b285502 100644 --- a/modules/congestion_controller/bbr/bbr_network_controller.cc +++ b/modules/congestion_controller/bbr/bbr_network_controller.cc @@ -237,7 +237,8 @@ void BbrNetworkController::Reset() { } } -NetworkControlUpdate BbrNetworkController::CreateRateUpdate(Timestamp at_time) { +NetworkControlUpdate BbrNetworkController::CreateRateUpdate( + Timestamp at_time) const { DataRate bandwidth = BandwidthEstimate(); if (bandwidth.IsZero()) bandwidth = default_bandwidth_; diff --git a/modules/congestion_controller/bbr/bbr_network_controller.h b/modules/congestion_controller/bbr/bbr_network_controller.h index 6246f14da4..8535d70d23 100644 --- a/modules/congestion_controller/bbr/bbr_network_controller.h +++ b/modules/congestion_controller/bbr/bbr_network_controller.h @@ -165,10 +165,10 @@ class BbrNetworkController : public NetworkControllerInterface { NetworkControlUpdate OnRoundTripTimeUpdate(RoundTripTimeUpdate msg) override; NetworkControlUpdate OnTransportLossReport(TransportLossReport msg) override; + NetworkControlUpdate CreateRateUpdate(Timestamp at_time) const; + private: void Reset(); - NetworkControlUpdate CreateRateUpdate(Timestamp at_time); - bool InSlowStart() const; bool InRecovery() const; bool IsProbingForMoreBandwidth() const; diff --git a/modules/congestion_controller/bbr/test/bbr_printer.cc b/modules/congestion_controller/bbr/test/bbr_printer.cc new file mode 100644 index 0000000000..440d49d25a --- /dev/null +++ b/modules/congestion_controller/bbr/test/bbr_printer.cc @@ -0,0 +1,57 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "modules/congestion_controller/bbr/test/bbr_printer.h" + +namespace webrtc { + +BbrStatePrinter::BbrStatePrinter() = default; +BbrStatePrinter::~BbrStatePrinter() = default; + +void BbrStatePrinter::Attach(bbr::BbrNetworkController* controller) { + controller_ = controller; +} + +bool BbrStatePrinter::Attached() const { + return controller_ != nullptr; +} + +void BbrStatePrinter::PrintHeaders(FILE* out) { + fprintf(out, "bbr_mode bbr_recovery_state round_trip_count gain_cycle_index"); +} + +void BbrStatePrinter::PrintValues(FILE* out) { + RTC_CHECK(controller_); + bbr::BbrNetworkController::DebugState debug(*controller_); + fprintf(out, "%i %i %i %i", debug.mode, debug.recovery_state, + static_cast(debug.round_trip_count), debug.gain_cycle_index); +} + +NetworkControlUpdate BbrStatePrinter::GetState(Timestamp at_time) const { + RTC_CHECK(controller_); + return controller_->CreateRateUpdate(at_time); +} + +BbrDebugFactory::BbrDebugFactory(BbrStatePrinter* printer) + : printer_(printer) {} + +std::unique_ptr BbrDebugFactory::Create( + NetworkControllerConfig config) { + RTC_CHECK(controller_ == nullptr); + auto controller = BbrNetworkControllerFactory::Create(config); + controller_ = static_cast(controller.get()); + printer_->Attach(controller_); + return controller; +} + +bbr::BbrNetworkController* BbrDebugFactory::BbrController() { + return controller_; +} + +} // namespace webrtc diff --git a/modules/congestion_controller/bbr/test/bbr_printer.h b/modules/congestion_controller/bbr/test/bbr_printer.h new file mode 100644 index 0000000000..75db53d866 --- /dev/null +++ b/modules/congestion_controller/bbr/test/bbr_printer.h @@ -0,0 +1,49 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef MODULES_CONGESTION_CONTROLLER_BBR_TEST_BBR_PRINTER_H_ +#define MODULES_CONGESTION_CONTROLLER_BBR_TEST_BBR_PRINTER_H_ + +#include + +#include "modules/congestion_controller/bbr/bbr_factory.h" +#include "modules/congestion_controller/bbr/bbr_network_controller.h" +#include "modules/congestion_controller/test/controller_printer.h" + +namespace webrtc { +class BbrStatePrinter : public DebugStatePrinter { + public: + BbrStatePrinter(); + ~BbrStatePrinter() override; + void Attach(bbr::BbrNetworkController*); + bool Attached() const override; + + void PrintHeaders(FILE* out) override; + void PrintValues(FILE* out) override; + + NetworkControlUpdate GetState(Timestamp at_time) const override; + + private: + bbr::BbrNetworkController* controller_ = nullptr; +}; + +class BbrDebugFactory : public BbrNetworkControllerFactory { + public: + explicit BbrDebugFactory(BbrStatePrinter* printer); + std::unique_ptr Create( + NetworkControllerConfig config) override; + bbr::BbrNetworkController* BbrController(); + + private: + BbrStatePrinter* printer_; + bbr::BbrNetworkController* controller_ = nullptr; +}; +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_BBR_TEST_BBR_PRINTER_H_ diff --git a/modules/congestion_controller/goog_cc/BUILD.gn b/modules/congestion_controller/goog_cc/BUILD.gn index bab967b399..502fb34fd2 100644 --- a/modules/congestion_controller/goog_cc/BUILD.gn +++ b/modules/congestion_controller/goog_cc/BUILD.gn @@ -143,6 +143,17 @@ rtc_source_set("delay_based_bwe") { } if (rtc_include_tests) { + rtc_source_set("test_goog_cc_printer") { + testonly = true + sources = [ + "test/goog_cc_printer.cc", + "test/goog_cc_printer.h", + ] + deps = [ + ":goog_cc", + "..:test_controller_printer", + ] + } rtc_source_set("goog_cc_unittests") { testonly = true diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 8c00ad8c05..9e62d844b0 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -336,6 +336,26 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( return update; } +NetworkControlUpdate GoogCcNetworkController::GetNetworkState( + Timestamp at_time) const { + DataRate bandwidth = DataRate::bps(last_estimated_bitrate_bps_); + TimeDelta rtt = TimeDelta::ms(last_estimated_rtt_ms_); + NetworkControlUpdate update; + update.target_rate = TargetTransferRate(); + update.target_rate->network_estimate.at_time = at_time; + update.target_rate->network_estimate.bandwidth = bandwidth; + update.target_rate->network_estimate.loss_rate_ratio = + last_estimated_fraction_loss_ / 255.0; + update.target_rate->network_estimate.round_trip_time = rtt; + update.target_rate->network_estimate.bwe_period = + TimeDelta::ms(delay_based_bwe_->GetExpectedBwePeriodMs()); + update.target_rate->at_time = at_time; + update.target_rate->target_rate = bandwidth; + update.pacer_config = UpdatePacingRates(at_time); + update.congestion_window = current_data_window_; + return update; +} + absl::optional GoogCcNetworkController::MaybeUpdateCongestionWindow() { if (!in_cwnd_experiment_) @@ -432,7 +452,8 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkEstimate( return update; } -PacerConfig GoogCcNetworkController::UpdatePacingRates(Timestamp at_time) { +PacerConfig GoogCcNetworkController::UpdatePacingRates( + Timestamp at_time) const { DataRate pacing_rate = std::max(min_pacing_rate_, last_bandwidth_) * pacing_factor_; DataRate padding_rate = std::min(max_padding_rate_, last_bandwidth_); diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/modules/congestion_controller/goog_cc/goog_cc_network_control.h index ba66fcef00..186f50cef3 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control.h +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.h @@ -49,6 +49,8 @@ class GoogCcNetworkController : public NetworkControllerInterface { NetworkControlUpdate OnTransportPacketsFeedback( TransportPacketsFeedback msg) override; + NetworkControlUpdate GetNetworkState(Timestamp at_time) const; + private: void UpdateBitrateConstraints(TargetRateConstraints constraints, absl::optional starting_rate); @@ -59,7 +61,7 @@ class GoogCcNetworkController : public NetworkControllerInterface { int64_t* rtt_ms, Timestamp at_time); NetworkControlUpdate OnNetworkEstimate(NetworkEstimate msg); - PacerConfig UpdatePacingRates(Timestamp at_time); + PacerConfig UpdatePacingRates(Timestamp at_time) const; RtcEventLog* const event_log_; diff --git a/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc b/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc new file mode 100644 index 0000000000..4c188669c4 --- /dev/null +++ b/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc @@ -0,0 +1,50 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "modules/congestion_controller/goog_cc/test/goog_cc_printer.h" +namespace webrtc { + +GoogCcStatePrinter::GoogCcStatePrinter() = default; +GoogCcStatePrinter::~GoogCcStatePrinter() = default; + +void GoogCcStatePrinter::Attach( + webrtc_cc::GoogCcNetworkController* controller) { + controller_ = controller; +} + +bool GoogCcStatePrinter::Attached() const { + return controller_ != nullptr; +} + +void GoogCcStatePrinter::PrintHeaders(FILE* out) {} + +void GoogCcStatePrinter::PrintValues(FILE* out) { + RTC_CHECK(controller_); +} + +NetworkControlUpdate GoogCcStatePrinter::GetState(Timestamp at_time) const { + RTC_CHECK(controller_); + return controller_->GetNetworkState(at_time); +} + +GoogCcDebugFactory::GoogCcDebugFactory(RtcEventLog* event_log, + GoogCcStatePrinter* printer) + : GoogCcNetworkControllerFactory(event_log), printer_(printer) {} + +std::unique_ptr GoogCcDebugFactory::Create( + NetworkControllerConfig config) { + RTC_CHECK(controller_ == nullptr); + auto controller = GoogCcNetworkControllerFactory::Create(config); + controller_ = + static_cast(controller.get()); + printer_->Attach(controller_); + return controller; +} + +} // namespace webrtc diff --git a/modules/congestion_controller/goog_cc/test/goog_cc_printer.h b/modules/congestion_controller/goog_cc/test/goog_cc_printer.h new file mode 100644 index 0000000000..907acfba85 --- /dev/null +++ b/modules/congestion_controller/goog_cc/test/goog_cc_printer.h @@ -0,0 +1,48 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_TEST_GOOG_CC_PRINTER_H_ +#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_TEST_GOOG_CC_PRINTER_H_ + +#include + +#include "modules/congestion_controller/goog_cc/goog_cc_network_control.h" +#include "modules/congestion_controller/goog_cc/include/goog_cc_factory.h" +#include "modules/congestion_controller/test/controller_printer.h" + +namespace webrtc { +class GoogCcStatePrinter : public DebugStatePrinter { + public: + GoogCcStatePrinter(); + ~GoogCcStatePrinter() override; + void Attach(webrtc_cc::GoogCcNetworkController*); + bool Attached() const override; + + void PrintHeaders(FILE* out) override; + void PrintValues(FILE* out) override; + + NetworkControlUpdate GetState(Timestamp at_time) const override; + + private: + webrtc_cc::GoogCcNetworkController* controller_ = nullptr; +}; + +class GoogCcDebugFactory : public GoogCcNetworkControllerFactory { + public: + GoogCcDebugFactory(RtcEventLog* event_log, GoogCcStatePrinter* printer); + std::unique_ptr Create( + NetworkControllerConfig config) override; + + private: + GoogCcStatePrinter* printer_; + webrtc_cc::GoogCcNetworkController* controller_ = nullptr; +}; +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_TEST_GOOG_CC_PRINTER_H_ diff --git a/modules/congestion_controller/test/controller_printer.cc b/modules/congestion_controller/test/controller_printer.cc new file mode 100644 index 0000000000..4c9c4fde8f --- /dev/null +++ b/modules/congestion_controller/test/controller_printer.cc @@ -0,0 +1,66 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "modules/congestion_controller/test/controller_printer.h" + +#include +#include +#include + +#include "rtc_base/checks.h" + +namespace webrtc { + +ControlStatePrinter::ControlStatePrinter( + FILE* output, + std::unique_ptr debug_printer) + : output_(output), debug_printer_(std::move(debug_printer)) {} + +ControlStatePrinter::~ControlStatePrinter() = default; + +void ControlStatePrinter::PrintHeaders() { + fprintf(output_, "time bandwidth rtt target pacing padding window"); + if (debug_printer_) { + fprintf(output_, " "); + debug_printer_->PrintHeaders(output_); + } + fprintf(output_, "\n"); + fflush(output_); +} + +void ControlStatePrinter::PrintState(const Timestamp time, + const NetworkControlUpdate state) { + double timestamp = time.seconds(); + auto estimate = state.target_rate->network_estimate; + double bandwidth = estimate.bandwidth.bps() / 8.0; + double rtt = estimate.round_trip_time.seconds(); + double target_rate = state.target_rate->target_rate.bps() / 8.0; + double pacing_rate = state.pacer_config->data_rate().bps() / 8.0; + double padding_rate = state.pacer_config->pad_rate().bps() / 8.0; + double congestion_window = state.congestion_window + ? state.congestion_window->bytes() + : std::numeric_limits::infinity(); + + fprintf(output_, "%f %f %f %f %f %f %f", timestamp, bandwidth, rtt, + target_rate, pacing_rate, padding_rate, congestion_window); + + if (debug_printer_) { + fprintf(output_, " "); + debug_printer_->PrintValues(output_); + } + fprintf(output_, "\n"); + fflush(output_); +} + +void ControlStatePrinter::PrintState(const Timestamp time) { + if (debug_printer_ && debug_printer_->Attached()) { + PrintState(time, debug_printer_->GetState(time)); + } +} +} // namespace webrtc diff --git a/modules/congestion_controller/test/controller_printer.h b/modules/congestion_controller/test/controller_printer.h new file mode 100644 index 0000000000..3c09b9142d --- /dev/null +++ b/modules/congestion_controller/test/controller_printer.h @@ -0,0 +1,43 @@ +/* + * Copyright 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef MODULES_CONGESTION_CONTROLLER_TEST_CONTROLLER_PRINTER_H_ +#define MODULES_CONGESTION_CONTROLLER_TEST_CONTROLLER_PRINTER_H_ + +#include +#include + +#include "api/transport/network_control.h" + +namespace webrtc { +class DebugStatePrinter { + public: + virtual bool Attached() const = 0; + virtual void PrintHeaders(FILE* out) = 0; + virtual void PrintValues(FILE* out) = 0; + virtual NetworkControlUpdate GetState(Timestamp at_time) const = 0; + virtual ~DebugStatePrinter() = default; +}; + +class ControlStatePrinter { + public: + ControlStatePrinter(FILE* output, + std::unique_ptr debug_printer); + ~ControlStatePrinter(); + void PrintHeaders(); + void PrintState(const Timestamp time, const NetworkControlUpdate state); + void PrintState(const Timestamp time); + + private: + FILE* output_; + std::unique_ptr debug_printer_; +}; +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_TEST_CONTROLLER_PRINTER_H_