SoftGLRender源码:Timer类

特性

文件:Base/Timer.h, Timer.cpp

这部分有2个类协作:Timer, ScopedTimer.

  • Timer 记录、计算一段时间长度,不提供超时回调.
  • ScopedTimer 通过RAII管理Timer资源,计算ScopedTimer类对象从构造到析构的时间.

获取时间:用<chrono>库提供的steady_clock::now()

std::chrono::time_point<std::chrono::steady_clock> start = std::chrono::steady_clock::now();

Timer类

计时功能

Timer类实现计时功能. 包含2个数据成员:start_, end_,分别用于记录起始时间、结束时间.

// Timer.h

class Timer {
public:
	void start(); // 开始计时
	void stop();  // 结束计时
	int64_t elapseMillis() const;

private:
	std::chrono::time_point<std::chrono::steady_clock> start_;
	std::chrono::time_point<std::chrono::steady_clock> end_;
};

记录起始时间:

void Timer::start() {
	start_ = std::chrono::steady_clock::now();
}

记录结束时间:

void Timer::stop() {
	end_ = std::chrono::steady_clock::now();
}

计算时间差:

int64_t Timer::elapseMillis() const {
	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_ - start_); // 单位:ms
	return duration.count();
}

3种计时:steady_clock, system_clock, high_resolution_clock

<chrono>库提供了3种时钟:steady_clock, system_clock, high_resolution_clock. 都能用于计时.

它们的区别:

  • steady_clock 稳定时钟

    • 单调递增的时钟,不受系统时间调整的影响
    • 适用于需要测量时间间隔的场景,如性能分析、超时计算等,时间不会倒退
    • 设计初衷是稳定且单调,每次调用now()得到的时间都比之前的大
  • system_clock 系统时钟

    • 系统范围的实时时钟(即“挂钟时间”),与实际时间(如UTC时间)相关
    • 适用于需要与日历交互的场景,如记录日志、文件时间戳等
    • 可能受系统时间调整的影响,例如用户手动修改系统时间或NTP同步
  • high_resolution_clock 高精度时钟

    • 提供尽可能高的时间分辨率(精度),适用于需要纳秒或微秒级计时的场景,如性能分析、基准测试
    • 大多数实现中,可能是steady_clock或system_clock别名,依赖于底层实现

虽然steady_clocksystem_clock,都能返回time_point类型数据,表示时间点信息. 但system_clock::time_point能转换成std::time_t,进而用C标准库函数(如std::localtime)转换为日历信息;

e.g. 将system_clock::time_point转换为日历信息

auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);

但是steady_clock::time_point无法转换,仅能计算时间差.

e.g. 用steady_clock::time_point计算时间差

auto start = std::chrono::steady_clock::now();
// ...操作...
auto end = std::chrono::steady_clock::now();
auto duration = end - start; // 计算时间间隔

ScopedTimer类

自动计时功能

利用RAII技术实现 作用域计时器. 核心功能:构造时,开始计时;析构时,结束计时,并输出耗时(ms)到日志系统.

class ScopedTimer {
public:
    // 构造时,需要指定一个字符串作为tag_
	ScopedTimer(const char* str) : tag_(str) {
		timer_.start();
	}
	~ScopedTimer() {
		timer_.stop();
		LOGD("TIMER %s: cost : %lld ms", tag_.c_str(), timer_.elapseMillis());
	}

	explicit operator bool() {
		return true;
	}

private:
	Timer timer_;     // 定时器
	std::string tag_; // 定时器标记
};

定时器标记tag_,是为了在log中标识定时器,方便用户查看.

内联宏使用ScopedTimer

为方便用户使用ScopedTimer计时,提供了一组宏

#ifndef NDEBUG
#	define FUNCTION_TIMED(X) SoftGL::ScopedTimer _functionTimer  = (X)
#	define SCOPED_TIMED(X)   if (SoftGL::ScopedTimer _scopeTimer = (X))
#else
#	define FUNCTION_TIMED(X)
#	define SCOPED_TIMED(X)
#endif // !NDEBUG

这样,用户只需要在需要计时的作用域使用该宏即可.

{
    FUNCTION_TIMED("VKContext::create");
    ...
} // 离开作用域,析构ScopedTimer对象,自动记录这段代码块的执行时间到日志
posted @ 2025-05-18 16:53  明明1109  阅读(31)  评论(0)    收藏  举报