[SlackedPacer] Add experiment arm for high precision if long queue time.

This CL adds flag "max_queue_time", e.g:
WebRTC-SlackedTaskQueuePacedSender/Enabled:true,max_queue_time:75ms

If the PacingController's ExpectedQueueTime() is greater than or equal
to "max_queue_time" then we will use high precision delayed tasks to
ensure a smoother (less bursty) pacing of packets.

This should only get triggered in ultra high definition scenarios or
temporarily during key frames being sent. I have confirmed manually that
with the flag set to 75 ms I get low precision when not sending key
frames and temporarily get high precision for 5-15 delayed tasks during
the sending of a key frame.

Bug: webrtc:13957
Change-Id: I3c8aeba5fe18812ed0187610cd3f92a375bc6f18
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/258623
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36538}
This commit is contained in:
Henrik Boström
2022-04-13 12:37:59 +02:00
committed by WebRTC LUCI CQ
parent 4d12174ca5
commit a768f5256a
2 changed files with 45 additions and 15 deletions

View File

@ -15,6 +15,8 @@
#include "absl/memory/memory.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/experiments/field_trial_units.h"
#include "rtc_base/trace_event.h"
namespace webrtc {
@ -28,6 +30,15 @@ constexpr const char* kSlackedTaskQueuePacedSenderFieldTrial =
const int TaskQueuePacedSender::kNoPacketHoldback = -1;
TaskQueuePacedSender::SlackedPacerFlags::SlackedPacerFlags(
const FieldTrialsView& field_trials)
: allow_low_precision("Enabled"),
max_low_precision_expected_queue_time("max_queue_time") {
ParseFieldTrial(
{&allow_low_precision, &max_low_precision_expected_queue_time},
field_trials.Lookup(kSlackedTaskQueuePacedSenderFieldTrial));
}
TaskQueuePacedSender::TaskQueuePacedSender(
Clock* clock,
PacingController::PacketSender* packet_sender,
@ -36,13 +47,13 @@ TaskQueuePacedSender::TaskQueuePacedSender(
TimeDelta max_hold_back_window,
int max_hold_back_window_in_packets)
: clock_(clock),
allow_low_precision_(
field_trials.IsEnabled(kSlackedTaskQueuePacedSenderFieldTrial)),
max_hold_back_window_(allow_low_precision_
slacked_pacer_flags_(field_trials),
max_hold_back_window_(slacked_pacer_flags_.allow_low_precision
? PacingController::kMinSleepTime
: max_hold_back_window),
max_hold_back_window_in_packets_(
allow_low_precision_ ? 0 : max_hold_back_window_in_packets),
max_hold_back_window_in_packets_(slacked_pacer_flags_.allow_low_precision
? 0
: max_hold_back_window_in_packets),
pacing_controller_(clock,
packet_sender,
field_trials,
@ -279,9 +290,19 @@ void TaskQueuePacedSender::MaybeProcessPackets(
next_process_time_ > next_send_time) {
// Prefer low precision if allowed and not probing.
TaskQueueBase::DelayPrecision precision =
allow_low_precision_ && !pacing_controller_.IsProbing()
slacked_pacer_flags_.allow_low_precision &&
!pacing_controller_.IsProbing()
? TaskQueueBase::DelayPrecision::kLow
: TaskQueueBase::DelayPrecision::kHigh;
// Optionally disable low precision if the expected queue time is greater
// than `max_low_precision_expected_queue_time`.
if (precision == TaskQueueBase::DelayPrecision::kLow &&
slacked_pacer_flags_.max_low_precision_expected_queue_time &&
pacing_controller_.ExpectedQueueTime() >=
slacked_pacer_flags_.max_low_precision_expected_queue_time
.Value()) {
precision = TaskQueueBase::DelayPrecision::kHigh;
}
task_queue_.PostDelayedTaskWithPrecision(
precision,

View File

@ -28,6 +28,7 @@
#include "modules/pacing/pacing_controller.h"
#include "modules/pacing/rtp_packet_pacer.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/numerics/exp_filter.h"
#include "rtc_base/task_queue.h"
#include "rtc_base/thread_annotations.h"
@ -129,16 +130,24 @@ class TaskQueuePacedSender : public RtpPacketPacer, public RtpPacketSender {
Stats GetStats() const;
Clock* const clock_;
// If `kSlackedTaskQueuePacedSenderFieldTrial` is enabled, delayed tasks
// invoking MaybeProcessPackets() are scheduled using low precision instead of
// high precision, resulting in less idle wake ups and packets being sent in
// bursts if the `task_queue_` implementation supports slack.
//
// When probing, high precision is used regardless of `allow_low_precision_`
// to ensure good bandwidth estimation.
const bool allow_low_precision_;
struct SlackedPacerFlags {
// Parses `kSlackedTaskQueuePacedSenderFieldTrial`. Example:
// --force-fieldtrials=WebRTC-SlackedTaskQueuePacedSender/Enabled,max_queue_time:75ms/
explicit SlackedPacerFlags(const FieldTrialsView& field_trials);
// When "Enabled", delayed tasks invoking MaybeProcessPackets() are
// scheduled using low precision instead of high precision, resulting in
// less idle wake ups and packets being sent in bursts if the `task_queue_`
// implementation supports slack. When probing, high precision is used
// regardless to ensure good bandwidth estimation.
FieldTrialFlag allow_low_precision;
// Controlled via the "max_queue_time" experiment arm. If set, uses high
// precision scheduling of MaybeProcessPackets() whenever the expected queue
// time is greater than or equal to this value.
FieldTrialOptional<TimeDelta> max_low_precision_expected_queue_time;
};
const SlackedPacerFlags slacked_pacer_flags_;
// The holdback window prevents too frequent delayed MaybeProcessPackets()
// calls. These are only applicable if `allow_low_precision_` is false.
// calls. These are only applicable if `allow_low_precision` is false.
const TimeDelta max_hold_back_window_;
const int max_hold_back_window_in_packets_;