Use unordered_map in ReceiveStatisticsImpl

In highly loaded media servers, ReceiveStatisticsImpl's use of std::map
attributes to ~0.32% CPU. It needs to be able to iterate through the
statisticians in order when reporting, but that is considered to be rare
compared to how often they are looked up. So this commit adds a separate
sorted set for just keeping track of the SSRCs, and letting the map of
SSRC to Statisticians, be unordered.

Bug: webrtc:12689
Change-Id: I69fe41d96bca31b2e8d669b58b5c7afabceaa6a6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/216385
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33864}
This commit is contained in:
Victor Boivie
2021-04-28 12:02:37 +02:00
committed by WebRTC LUCI CQ
parent aeff995ca8
commit b2f8c1675d
2 changed files with 23 additions and 23 deletions

View File

@ -321,7 +321,7 @@ ReceiveStatisticsImpl::ReceiveStatisticsImpl(
int max_reordering_threshold)> stream_statistician_factory)
: clock_(clock),
stream_statistician_factory_(std::move(stream_statistician_factory)),
last_returned_ssrc_(0),
last_returned_ssrc_idx_(0),
max_reordering_threshold_(kDefaultMaxReorderingThreshold) {}
void ReceiveStatisticsImpl::OnRtpPacket(const RtpPacketReceived& packet) {
@ -346,6 +346,7 @@ StreamStatisticianImplInterface* ReceiveStatisticsImpl::GetOrCreateStatistician(
if (impl == nullptr) { // new element
impl =
stream_statistician_factory_(ssrc, clock_, max_reordering_threshold_);
all_ssrcs_.push_back(ssrc);
}
return impl.get();
}
@ -373,14 +374,20 @@ void ReceiveStatisticsImpl::EnableRetransmitDetection(uint32_t ssrc,
std::vector<rtcp::ReportBlock> ReceiveStatisticsImpl::RtcpReportBlocks(
size_t max_blocks) {
std::vector<rtcp::ReportBlock> result;
result.reserve(std::min(max_blocks, statisticians_.size()));
auto add_report_block = [&result](
uint32_t media_ssrc,
StreamStatisticianImplInterface* statistician) {
result.reserve(std::min(max_blocks, all_ssrcs_.size()));
size_t ssrc_idx = 0;
for (size_t i = 0; i < all_ssrcs_.size() && result.size() < max_blocks; ++i) {
ssrc_idx = (last_returned_ssrc_idx_ + i + 1) % all_ssrcs_.size();
const uint32_t media_ssrc = all_ssrcs_[ssrc_idx];
auto statistician_it = statisticians_.find(media_ssrc);
RTC_DCHECK(statistician_it != statisticians_.end());
// Do we have receive statistics to send?
RtcpStatistics stats;
if (!statistician->GetActiveStatisticsAndReset(&stats))
return;
if (!statistician_it->second->GetActiveStatisticsAndReset(&stats))
continue;
result.emplace_back();
rtcp::ReportBlock& block = result.back();
block.SetMediaSsrc(media_ssrc);
@ -388,22 +395,12 @@ std::vector<rtcp::ReportBlock> ReceiveStatisticsImpl::RtcpReportBlocks(
if (!block.SetCumulativeLost(stats.packets_lost)) {
RTC_LOG(LS_WARNING) << "Cumulative lost is oversized.";
result.pop_back();
return;
continue;
}
block.SetExtHighestSeqNum(stats.extended_highest_sequence_number);
block.SetJitter(stats.jitter);
};
const auto start_it = statisticians_.upper_bound(last_returned_ssrc_);
for (auto it = start_it;
result.size() < max_blocks && it != statisticians_.end(); ++it)
add_report_block(it->first, it->second.get());
for (auto it = statisticians_.begin();
result.size() < max_blocks && it != start_it; ++it)
add_report_block(it->first, it->second.get());
if (!result.empty())
last_returned_ssrc_ = result.back().source_ssrc();
}
last_returned_ssrc_idx_ = ssrc_idx;
return result;
}

View File

@ -13,8 +13,8 @@
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>
@ -187,9 +187,12 @@ class ReceiveStatisticsImpl : public ReceiveStatistics {
Clock* clock,
int max_reordering_threshold)>
stream_statistician_factory_;
uint32_t last_returned_ssrc_;
// The index within `all_ssrcs_` that was last returned.
size_t last_returned_ssrc_idx_;
std::vector<uint32_t> all_ssrcs_;
int max_reordering_threshold_;
std::map<uint32_t, std::unique_ptr<StreamStatisticianImplInterface>>
std::unordered_map<uint32_t /*ssrc*/,
std::unique_ptr<StreamStatisticianImplInterface>>
statisticians_;
};