Mediasoup之RateCalculator(流量统计)

本文详细解读了Mediasoup中的RateCalculator类,介绍了其如何通过滑动窗口原理统计比特流,并展示了关键公式。重点讲解了Update和GetRate方法的工作机制,以及比特流的计算方法。
摘要由CSDN通过智能技术生成

一、Mediasoup之RateCalculator(流量统计)

mediasoup中使用RateCalculator记录每个毫秒数比特流的数据的,

二、 分析RateCalculator类的方法

大致的思想是: 滑动窗口总时间和滑动窗口个数, 就可以得到每个具体滑动窗口占有毫秒, 就是每个窗口比特流 总和 除以总窗口的数量就是大致的比特流

class RateCalculator
	{
	public:
		static constexpr size_t DefaultWindowSize{ 1000u }; // 默认滑动窗口占有毫秒数
		static constexpr float DefaultBpsScale{ 8000.0f };// 比特流
		static constexpr uint16_t DefaultWindowItems{ 100u };// 滑动窗口有多少个

	public:
		RateCalculator(
		  size_t windowSizeMs  = DefaultWindowSize,
		  float scale          = DefaultBpsScale,
		  uint16_t windowItems = DefaultWindowItems)
		  : windowSizeMs(windowSizeMs), scale(scale), windowItems(windowItems)
		{
			this->itemSizeMs = std::max(windowSizeMs / windowItems, static_cast<size_t>(1));

			Reset();
		}
		void Update(size_t size, uint64_t nowMs);
		uint32_t GetRate(uint64_t nowMs);
		size_t GetBytes() const
		{
			return this->bytes;
		}

	private:
		void RemoveOldData(uint64_t nowMs);
		void Reset()
		{
			this->buffer.reset(new BufferItem[this->windowItems]);
			this->newestItemStartTime = 0u;
			this->newestItemIndex     = -1;
			this->oldestItemStartTime = 0u;
			this->oldestItemIndex     = -1;
			this->totalCount          = 0u;
			this->lastRate            = 0u;
			this->lastTime            = 0u;
		}

	private:
		struct BufferItem
		{
			size_t count{ 0u };
			uint64_t time{ 0u };
		};

	private:
		// Window Size (in milliseconds).
		size_t windowSizeMs{ DefaultWindowSize }; // 滑动窗口的大小毫秒数
		// Scale in which the rate is represented.
		float scale{ DefaultBpsScale }; // 表示比率的刻度。
		// Window Size (number of items).
		uint16_t windowItems{ DefaultWindowItems }; // 滑动窗口的数组个数
		// Item Size (in milliseconds), calculated as: windowSizeMs / windowItems.
		size_t itemSizeMs{ 0u }; // 每个滑动窗口占有毫秒数
		// Buffer to keep data.
		std::unique_ptr<BufferItem[]> buffer; // 滑动窗口的数组记录数据集
		// Time (in milliseconds) for last item in the time window.
		uint64_t newestItemStartTime{ 0u }; // 当前最新窗口的时间毫秒数
		// Index for the last item in the time window.
		int32_t newestItemIndex{ -1 }; // 最新的窗口的下标
		// Time (in milliseconds) for oldest item in the time window.
		uint64_t oldestItemStartTime{ 0u }; // 总是记录滑动窗口中最小毫秒数
		// Index for the oldest item in the time window.
		int32_t oldestItemIndex{ -1 }; // 最老的下标
		// Total count in the time window.
		size_t totalCount{ 0u }; // 数据同和当前
		// Total bytes transmitted.
		size_t bytes{ 0u };
		// Last value calculated by GetRate().
		uint32_t lastRate{ 0u };
		// Last time GetRate() was called.
		uint64_t lastTime{ 0u };
	};


void RateCalculator::Update(size_t size, uint64_t nowMs)
	{
		MS_TRACE();

		// Ignore too old data. Should never happen.
		if (nowMs < this->oldestItemStartTime)
		{
			return;
		}

		// Increase bytes.
		this->bytes += size;

		RemoveOldData(nowMs);

		// If the elapsed time from the newest item start time is greater than the
		// item size (in milliseconds), increase the item index.
		if (this->newestItemIndex < 0 || nowMs - this->newestItemStartTime >= this->itemSizeMs)
		{
			this->newestItemIndex++;
			this->newestItemStartTime = nowMs;
			if (this->newestItemIndex >= this->windowItems)
			{
				this->newestItemIndex = 0;
			}

			// Newest index overlaps with the oldest one, remove it.
			if (this->newestItemIndex == this->oldestItemIndex && this->oldestItemIndex != -1)
			{
				MS_WARN_TAG(
				  info,
				  "calculation buffer full, windowSizeMs:%zu ms windowItems:%" PRIu16,
				  this->windowSizeMs,
				  this->windowItems);

				BufferItem& oldestItem = buffer[this->oldestItemIndex];
				this->totalCount -= oldestItem.count;
				oldestItem.count = 0u;
				oldestItem.time  = 0u;
				if (++this->oldestItemIndex >= this->windowItems)
				{
					this->oldestItemIndex = 0;
				}
			}

			// Set the newest item.
			BufferItem& item = buffer[this->newestItemIndex];
			item.count       = size;
			item.time        = nowMs;
		}
		else
		{
			// Update the newest item.
			BufferItem& item = buffer[this->newestItemIndex];
			item.count += size;
		}

		// Set the oldest item index and time, if not set.
		if (this->oldestItemIndex < 0)
		{
			this->oldestItemIndex     = this->newestItemIndex;
			this->oldestItemStartTime = nowMs;
		}

		this->totalCount += size;

		// Reset lastRate and lastTime so GetRate() will calculate rate again even
		// if called with same now in the same loop iteration.
		this->lastRate = 0;
		this->lastTime = 0;
	}

	uint32_t RateCalculator::GetRate(uint64_t nowMs)
	{
		MS_TRACE();

		if (nowMs == this->lastTime)
		{
			return this->lastRate;
		}

		RemoveOldData(nowMs);

		// 比特流 / 总的滑动窗口毫秒数
		float scale = this->scale / this->windowSizeMs;

		this->lastTime = nowMs;
		// 具体就是滑动窗口比特流的公式 =  总滑动窗口中有的数据的总和 * 8000 / windowsizems  ;
		// 原来我以为有什么特殊公式呢!!!
		this->lastRate = static_cast<uint32_t>(std::trunc(this->totalCount * scale + 0.5f));
		//trunc()函数是cmath标头的库函数,用于将值四舍五入(截断)为零,它接受一个数字并返回其大小不大于给定数字的最近整数值。
		return this->lastRate;
	}

	inline void RateCalculator::RemoveOldData(uint64_t nowMs)
	{
		MS_TRACE();

		// No item set.
		if (this->newestItemIndex < 0 || this->oldestItemIndex < 0)
		{
			return;
		}
		// 1. 这个值是根据 当前毫秒数减去全部的滑动窗口时间来计算的     
		uint64_t newoldestTime = nowMs - this->windowSizeMs;

		// 2. 判断是否小于滑动窗口中最小的时间毫秒数 , 如果小于就不需要处理哈(滑动窗口中没有计算该值哈)
		// Oldest item already removed.
		if (newoldestTime <= this->oldestItemStartTime)
		{
			return;
		}
		// 说明上次发送数据时间长太长, 超出滑动窗口的时间长 需要重置滑动窗口
		// A whole window size time has elapsed since last entry. Reset the buffer.
		if (newoldestTime > this->newestItemStartTime)
		{
			Reset();

			return;
		}
		// 移除超出滑动窗口时间的数据 count 
		while (this->oldestItemStartTime < newoldestTime)
		{
			BufferItem& oldestItem = buffer[this->oldestItemIndex];
			this->totalCount -= oldestItem.count;
			oldestItem.count = 0u;
			oldestItem.time  = 0u;

			if (++this->oldestItemIndex >= this->windowItems)
			{
				this->oldestItemIndex = 0;
			}

			const BufferItem& newOldestItem = buffer[this->oldestItemIndex];
			// 总是记录滑动窗口中最小毫秒数
			this->oldestItemStartTime       = newOldestItem.time;
		}
	}

三、 比特流的公式

公式 = 总滑动窗口中有的数据的总和 * 8000 / windowsizems ;

对应的代码

		// 比特流 / 总的滑动窗口毫秒数
		float scale = this->scale / this->windowSizeMs;

		this->lastTime = nowMs;
		// 具体就是滑动窗口比特流的公式 =  总滑动窗口中有的数据的总和 * 8000 / windowsizems  ;
		this->lastRate = static_cast<uint32_t>(std::trunc(this->totalCount * scale + 0.5f));

总结:

在Mediasoup中RateCalculator也没有啥大的作用, 作为流量统计数据分析

源码地址:https://github.com/chensongpoixs/cmediasoup/blob/master/src/RTC/RateCalculator.cpp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值