Cleanup usage of lookups in video SendDelayStats helper

Remove redundant ssrc_ set, instead construct send_delay_stats_ early
Remove extra lookup when packet is sent out, instead memorize pointer to needed object
minor style improvments using syntax new in c++17

Bug: None
Change-Id: I0f0e28f5a01de0380502d4bee64cdf76e44a59cd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/317760
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40630}
This commit is contained in:
Danil Chapovalov 2023-08-25 09:40:15 +00:00 committed by WebRTC LUCI CQ
parent b971a534e9
commit 8cfae1bb3f
2 changed files with 29 additions and 41 deletions

View file

@ -20,11 +20,11 @@ namespace {
// Packet with a larger delay are removed and excluded from the delay stats. // Packet with a larger delay are removed and excluded from the delay stats.
// Set to larger than max histogram delay which is 10 seconds. // Set to larger than max histogram delay which is 10 seconds.
constexpr TimeDelta kMaxSentPacketDelay = TimeDelta::Seconds(11); constexpr TimeDelta kMaxSentPacketDelay = TimeDelta::Seconds(11);
const size_t kMaxPacketMapSize = 2000; constexpr size_t kMaxPacketMapSize = 2000;
// Limit for the maximum number of streams to calculate stats for. // Limit for the maximum number of streams to calculate stats for.
const size_t kMaxSsrcMapSize = 50; constexpr size_t kMaxSsrcMapSize = 50;
const int kMinRequiredPeriodicSamples = 5; constexpr int kMinRequiredPeriodicSamples = 5;
} // namespace } // namespace
SendDelayStats::SendDelayStats(Clock* clock) SendDelayStats::SendDelayStats(Clock* clock)
@ -42,8 +42,8 @@ SendDelayStats::~SendDelayStats() {
void SendDelayStats::UpdateHistograms() { void SendDelayStats::UpdateHistograms() {
MutexLock lock(&mutex_); MutexLock lock(&mutex_);
for (const auto& it : send_delay_counters_) { for (auto& [unused, counter] : send_delay_counters_) {
AggregatedStats stats = it.second->GetStats(); AggregatedStats stats = counter.GetStats();
if (stats.num_samples >= kMinRequiredPeriodicSamples) { if (stats.num_samples >= kMinRequiredPeriodicSamples) {
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SendDelayInMs", stats.average); RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SendDelayInMs", stats.average);
RTC_LOG(LS_INFO) << "WebRTC.Video.SendDelayInMs, " << stats.ToString(); RTC_LOG(LS_INFO) << "WebRTC.Video.SendDelayInMs, " << stats.ToString();
@ -53,20 +53,11 @@ void SendDelayStats::UpdateHistograms() {
void SendDelayStats::AddSsrcs(const VideoSendStream::Config& config) { void SendDelayStats::AddSsrcs(const VideoSendStream::Config& config) {
MutexLock lock(&mutex_); MutexLock lock(&mutex_);
if (ssrcs_.size() > kMaxSsrcMapSize) if (send_delay_counters_.size() + config.rtp.ssrcs.size() > kMaxSsrcMapSize)
return; return;
for (const auto& ssrc : config.rtp.ssrcs) for (uint32_t ssrc : config.rtp.ssrcs) {
ssrcs_.insert(ssrc); send_delay_counters_.try_emplace(ssrc, clock_, nullptr, false);
} }
AvgCounter* SendDelayStats::GetSendDelayCounter(uint32_t ssrc) {
const auto& it = send_delay_counters_.find(ssrc);
if (it != send_delay_counters_.end())
return it->second.get();
AvgCounter* counter = new AvgCounter(clock_, nullptr, false);
send_delay_counters_[ssrc].reset(counter);
return counter;
} }
void SendDelayStats::OnSendPacket(uint16_t packet_id, void SendDelayStats::OnSendPacket(uint16_t packet_id,
@ -74,17 +65,24 @@ void SendDelayStats::OnSendPacket(uint16_t packet_id,
uint32_t ssrc) { uint32_t ssrc) {
// Packet sent to transport. // Packet sent to transport.
MutexLock lock(&mutex_); MutexLock lock(&mutex_);
if (ssrcs_.find(ssrc) == ssrcs_.end()) auto it = send_delay_counters_.find(ssrc);
if (it == send_delay_counters_.end())
return; return;
Timestamp now = clock_->CurrentTime(); Timestamp now = clock_->CurrentTime();
RemoveOld(now, &packets_); RemoveOld(now);
if (packets_.size() > kMaxPacketMapSize) { if (packets_.size() > kMaxPacketMapSize) {
++num_skipped_packets_; ++num_skipped_packets_;
return; return;
} }
packets_.insert(std::make_pair(packet_id, Packet(ssrc, capture_time, now))); // `send_delay_counters_` is an std::map - adding new entries doesn't
// invalidate existent iterators, and it has pointer stability for values.
// Entries are never remove from the `send_delay_counters_`.
// Thus memorizing pointer to the AvgCounter is safe.
packets_.emplace(packet_id, Packet{.send_delay = &it->second,
.capture_time = capture_time,
.send_time = now});
} }
bool SendDelayStats::OnSentPacket(int packet_id, Timestamp time) { bool SendDelayStats::OnSentPacket(int packet_id, Timestamp time) {
@ -100,18 +98,18 @@ bool SendDelayStats::OnSentPacket(int packet_id, Timestamp time) {
// TODO(asapersson): Remove SendSideDelayUpdated(), use capture -> sent. // TODO(asapersson): Remove SendSideDelayUpdated(), use capture -> sent.
// Elapsed time from send (to transport) -> sent (leaving socket). // Elapsed time from send (to transport) -> sent (leaving socket).
TimeDelta diff = time - it->second.send_time; TimeDelta diff = time - it->second.send_time;
GetSendDelayCounter(it->second.ssrc)->Add(diff.ms()); it->second.send_delay->Add(diff.ms());
packets_.erase(it); packets_.erase(it);
return true; return true;
} }
void SendDelayStats::RemoveOld(Timestamp now, PacketMap* packets) { void SendDelayStats::RemoveOld(Timestamp now) {
while (!packets->empty()) { while (!packets_.empty()) {
auto it = packets->begin(); auto it = packets_.begin();
if (now - it->second.capture_time < kMaxSentPacketDelay) if (now - it->second.capture_time < kMaxSentPacketDelay)
break; break;
packets->erase(it); packets_.erase(it);
++num_old_packets_; ++num_old_packets_;
} }
} }

View file

@ -15,8 +15,6 @@
#include <stdint.h> #include <stdint.h>
#include <map> #include <map>
#include <memory>
#include <set>
#include "api/units/timestamp.h" #include "api/units/timestamp.h"
#include "call/video_send_stream.h" #include "call/video_send_stream.h"
@ -61,32 +59,24 @@ class SendDelayStats : public SendPacketObserver {
} }
}; };
struct Packet { struct Packet {
Packet(uint32_t ssrc, Timestamp capture_time, Timestamp send_time) AvgCounter* send_delay;
: ssrc(ssrc), capture_time(capture_time), send_time(send_time) {}
uint32_t ssrc;
Timestamp capture_time; Timestamp capture_time;
Timestamp send_time; Timestamp send_time;
}; };
typedef std::map<uint16_t, Packet, SequenceNumberOlderThan> PacketMap;
void UpdateHistograms(); void UpdateHistograms();
void RemoveOld(Timestamp now, PacketMap* packets) void RemoveOld(Timestamp now) RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
AvgCounter* GetSendDelayCounter(uint32_t ssrc)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Clock* const clock_; Clock* const clock_;
Mutex mutex_; Mutex mutex_;
PacketMap packets_ RTC_GUARDED_BY(mutex_); std::map<uint16_t, Packet, SequenceNumberOlderThan> packets_
RTC_GUARDED_BY(mutex_);
size_t num_old_packets_ RTC_GUARDED_BY(mutex_); size_t num_old_packets_ RTC_GUARDED_BY(mutex_);
size_t num_skipped_packets_ RTC_GUARDED_BY(mutex_); size_t num_skipped_packets_ RTC_GUARDED_BY(mutex_);
std::set<uint32_t> ssrcs_ RTC_GUARDED_BY(mutex_);
// Mapped by SSRC. // Mapped by SSRC.
std::map<uint32_t, std::unique_ptr<AvgCounter>> send_delay_counters_ std::map<uint32_t, AvgCounter> send_delay_counters_ RTC_GUARDED_BY(mutex_);
RTC_GUARDED_BY(mutex_);
}; };
} // namespace webrtc } // namespace webrtc