前言

我们编写程序时,有时需要统计代码运行时间,比如记录视频解码耗时,以及视频的播放帧率等以确认性能满足,或者记录代码运行时长作为优化的依据。通常的做法是定义一个变量记录起始时间,在结束时获取当前时间减去起始时间,本文为C++版本将上述操作封装为一些对象方便使用。


一、计算范围时间

我们使用chrono就很容易做到。

1、起始位置

_d = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() / 1e+9;;

2、结束位置

_time = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() / 1e+9; -_d;

3、获取时间

//单位秒
std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() / 1e+9;

封装成对象

(1)、完整代码

#include <iostream>
#include <chrono>
#include <queue>

class RangeCodeTime
{
	std::queue<double> _times;
	double _time = 0;
	double _average = 0;
	double _d = 0;
	double _sum = 0;
	int _maxAvgCount = 60;
public:
	double GetTime()
	{
		return _time;
	}
	double GetAverage()
	{
		return _average;
	}
	void Begin()
	{
		_d = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() / 1e+9;
	}
	void End(const std::string& printLabel = "", bool isPrint = true)
	{
		_time = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() / 1e+9 -_d;
		_times.push(_time);
		_sum += _time;
		_average = _sum / _times.size();
		if (_times.size() >= _maxAvgCount)
		{
			_sum -= _times.front();
			_times.pop();
		}
		if (isPrint)
		{
			printf("%s当前耗时(s):%lf 平均耗时(s):%lf\n", printLabel.c_str(), _time, _average);
		}
	}
};

(2)、使用示例

RangeCodeTime rct ;

int main()
{
	rct.Begin();
	//需要计算时长的代码
	//默认会输出到控制台,isPrint=true。也可以在End()之后通过属性Time、和Average获取数据。
	rct.End("采集");
}

效果预览
在这里插入图片描述


二、计算检查点时间

检查点通常可以用于计算循环或者回调的耗时,比如播放视频过程中放置一个检查点,就可以计算出帧率。

1、定义变量

double _d = 0;

2、检查点

auto currentTime = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() / 1e+9;
if (_d == 0)
{
	_d = currentTime;
	return;
}
_time = currentTime - _d;

封装成对象

(1)、完整代码

class CheckPointCodeTime
{
	std::queue<double> _times;
	double _time = 0;
	double _average = 0;
	double _d = 0;
	double _sum = 0;
	int _maxAvgCount = 60;

public:
	double GetTime()
	{
		return _time;
	}
	double GetAverage()
	{
		return _average;
	}
	void Check(const std::string& printLabel = "", bool isPrint = true)
	{
		auto currentTime = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() / 1e+9;
		if (_d == 0)
		{
			_d = currentTime;
			return;
		}
		_time = currentTime - _d;
		_d = currentTime;
		_times.push(_time);
		_sum += _time;
		_average = _sum / _times.size();
		if (_times.size() >= _maxAvgCount)
		{
			_sum -= _times.front();
			_times.pop();
		}
		if (isPrint)
		{
			printf("%s当前耗时(s):%lf 平均耗时(s):%lf\n", printLabel.c_str(), _time, _average);
		}
	}
};

(2)、使用示例

CheckPointCodeTime cct;
int main()
{
	while (1) {
		//默认会输出到控制台,isPrint=true。也可以在Check()之后通过属性Time、和Average获取数据。
		cct.Check("接收一帧 ");
		//其他处理
	}
}

效果预览
在这里插入图片描述


总结

以上就是今天要讲的内容,本文简单对chrono进行了一个封装,主要目的是方便调用,而且也将均值计算出来了,这样有利于对数据的统计,总的来说还是有一定适用场景的。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐