Add parameter to control the pacer's burst outside of field trials.
BurstyPacer is currently controlled via field trials. In order for Chrome to be able to have burst without relying on a field trial, this parameter is added. When all burst experiments have concluded we may be able to have a hardcoded constant instead, but for now the parameter is added to RTCConfiguration. NOTRY=True Bug: chromium:1354491 Change-Id: I386c1651dbbcbf309c15ea3d3380cf8f632b5429 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/283420 Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/main@{#38621}
This commit is contained in:
committed by
WebRTC LUCI CQ
parent
b21c979691
commit
cf2856b01c
@ -57,7 +57,8 @@ TaskQueuePacedSender::TaskQueuePacedSender(
|
||||
const FieldTrialsView& field_trials,
|
||||
TaskQueueFactory* task_queue_factory,
|
||||
TimeDelta max_hold_back_window,
|
||||
int max_hold_back_window_in_packets)
|
||||
int max_hold_back_window_in_packets,
|
||||
absl::optional<TimeDelta> burst_interval)
|
||||
: clock_(clock),
|
||||
bursty_pacer_flags_(field_trials),
|
||||
slacked_pacer_flags_(field_trials),
|
||||
@ -85,6 +86,12 @@ TaskQueuePacedSender::TaskQueuePacedSender(
|
||||
burst = slacked_burst;
|
||||
}
|
||||
}
|
||||
// Burst can also be controlled via the `burst_interval` argument.
|
||||
if (burst_interval.has_value() &&
|
||||
(!burst.has_value() || burst.value() < burst_interval.value())) {
|
||||
burst = burst_interval;
|
||||
}
|
||||
|
||||
if (burst.has_value()) {
|
||||
pacing_controller_.SetSendBurstInterval(burst.value());
|
||||
}
|
||||
|
||||
@ -39,16 +39,25 @@ class TaskQueuePacedSender : public RtpPacketPacer, public RtpPacketSender {
|
||||
public:
|
||||
static const int kNoPacketHoldback;
|
||||
|
||||
// The pacer can be configured using `field_trials` or specified parameters.
|
||||
//
|
||||
// The `hold_back_window` parameter sets a lower bound on time to sleep if
|
||||
// there is currently a pacer queue and packets can't immediately be
|
||||
// processed. Increasing this reduces thread wakeups at the expense of higher
|
||||
// latency.
|
||||
TaskQueuePacedSender(Clock* clock,
|
||||
PacingController::PacketSender* packet_sender,
|
||||
const FieldTrialsView& field_trials,
|
||||
TaskQueueFactory* task_queue_factory,
|
||||
TimeDelta max_hold_back_window,
|
||||
int max_hold_back_window_in_packets);
|
||||
//
|
||||
// If the `burst_interval` parameter is set, the pacer is allowed to build up
|
||||
// a packet "debt" that correspond to approximately the send rate during the
|
||||
// specified interval. This greatly reduced wake ups by not pacing packets
|
||||
// within the allowed burst budget.
|
||||
TaskQueuePacedSender(
|
||||
Clock* clock,
|
||||
PacingController::PacketSender* packet_sender,
|
||||
const FieldTrialsView& field_trials,
|
||||
TaskQueueFactory* task_queue_factory,
|
||||
TimeDelta max_hold_back_window,
|
||||
int max_hold_back_window_in_packets,
|
||||
absl::optional<TimeDelta> burst_interval = absl::nullopt);
|
||||
|
||||
~TaskQueuePacedSender() override;
|
||||
|
||||
|
||||
@ -253,6 +253,53 @@ TEST_P(TaskQueuePacedSenderTest, PacesPackets) {
|
||||
EXPECT_NEAR((end_time - start_time).ms<double>(), 1000.0, 50.0);
|
||||
}
|
||||
|
||||
// Same test as above, but with 0.5s of burst applied.
|
||||
TEST_P(TaskQueuePacedSenderTest, PacesPacketsWithBurst) {
|
||||
GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
|
||||
MockPacketRouter packet_router;
|
||||
ScopedKeyValueConfig trials(GetParam());
|
||||
TaskQueuePacedSender pacer(time_controller.GetClock(), &packet_router, trials,
|
||||
time_controller.GetTaskQueueFactory(),
|
||||
PacingController::kMinSleepTime,
|
||||
TaskQueuePacedSender::kNoPacketHoldback,
|
||||
// Half a second of bursting.
|
||||
TimeDelta::Seconds(0.5));
|
||||
|
||||
// Insert a number of packets, covering one second.
|
||||
static constexpr size_t kPacketsToSend = 42;
|
||||
SequenceChecker sequence_checker;
|
||||
pacer.SetPacingRates(
|
||||
DataRate::BitsPerSec(kDefaultPacketSize * 8 * kPacketsToSend),
|
||||
DataRate::Zero());
|
||||
pacer.EnsureStarted();
|
||||
pacer.EnqueuePackets(
|
||||
GeneratePackets(RtpPacketMediaType::kVideo, kPacketsToSend));
|
||||
|
||||
// Expect all of them to be sent.
|
||||
size_t packets_sent = 0;
|
||||
Timestamp end_time = Timestamp::PlusInfinity();
|
||||
EXPECT_CALL(packet_router, SendPacket)
|
||||
.WillRepeatedly([&](std::unique_ptr<RtpPacketToSend> packet,
|
||||
const PacedPacketInfo& cluster_info) {
|
||||
++packets_sent;
|
||||
if (packets_sent == kPacketsToSend) {
|
||||
end_time = time_controller.GetClock()->CurrentTime();
|
||||
}
|
||||
EXPECT_EQ(sequence_checker.IsCurrent(), UsingWorkerThread(GetParam()));
|
||||
});
|
||||
|
||||
const Timestamp start_time = time_controller.GetClock()->CurrentTime();
|
||||
|
||||
// Packets should be sent over a period of close to 1s. Expect a little
|
||||
// lower than this since initial probing is a bit quicker.
|
||||
time_controller.AdvanceTime(TimeDelta::Seconds(1));
|
||||
EXPECT_EQ(packets_sent, kPacketsToSend);
|
||||
ASSERT_TRUE(end_time.IsFinite());
|
||||
// Because of half a second of burst, what would normally have been paced over
|
||||
// ~1 second now takes ~0.5 seconds.
|
||||
EXPECT_NEAR((end_time - start_time).ms<double>(), 500.0, 50.0);
|
||||
}
|
||||
|
||||
TEST_P(TaskQueuePacedSenderTest, ReschedulesProcessOnRateChange) {
|
||||
GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
|
||||
MockPacketRouter packet_router;
|
||||
|
||||
Reference in New Issue
Block a user