不到100行代碼,封裝一個通用毫秒級計時器(基于RAII思想)
[TOC]
腳步不停,終達卓越!更多優(yōu)質文章及代碼資源詳見公眾號 《開源519》
引言
? 在C/C++開發(fā)中,測量代碼執(zhí)行時間是性能分析、定時任務或超時檢測等場景的常見需求。雖然可以直接調用系統(tǒng)接口實現,但這種方式重復代碼多、可維護性差。
? 高質量的程序員會傾向于將其封裝為一個結構清晰、使用直觀的類,以提升代碼復用性和可讀性,同時便于統(tǒng)一管理和功能擴展。面對此類需求,RAII(Resource Acquisition Is Initialization) 原則恰好為設計高效、可靠的計時器提供了理想的理論基礎。
RAII,也稱為“資源獲取就是初始化”,是c++等編程語言常用的管理資源、避免內存泄露的方法。它保證在任何情況下,使用對象時先構造對象,最后析構對象。
需求分析
? 基于日常開發(fā)對于計時器的使用需求,大致如下:
- 使用簡單
對外接口盡可能少,理論只需要提供獲取執(zhí)行時長的接口即可。 - 計時精度毫秒級
提供獲取時長的接口精度轉換至毫秒級。 - 可復用性強
提供一套統(tǒng)一且穩(wěn)定的接口,確保在不同項目或模塊中可以方便地重用代碼。
詳細設計
? 實現起來很簡單,主要是在封裝上做文章。
RunningTiming.h
#ifndef __RUNNING_TIMING_H__
#define __RUNNING_TIMING_H__
#include <stdint.h>
class RunningTiming
{
public:
RunningTiming();
~RunningTiming();
uint64_t GetElapsedTimeInSec();
uint64_t GetElapsedTimeInMSec();
private:
uint64_t GetCurTimeInMSec();
private:
uint64_t mStartTimeInMSec;
};
#endif // __RUNNING_TIMING_H__
RunningTiming.cpp
#include <time.h>
#include <sys/time.h>
#include "RunningTiming.h"
RunningTiming::RunningTiming()
{
mStartTimeInMSec = GetCurTimeInMSec();
}
RunningTiming::~RunningTiming()
{
}
uint64_t RunningTiming::GetCurTimeInMSec() {
timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
uint64_t timeInMSec = static_cast<uint64_t>(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
return timeInMSec;
}
uint64_t RunningTiming::GetElapsedTimeInSec()
{
uint64_t stopTimeInMsec = GetCurTimeInMSec();
return (stopTimeInMsec - mStartTimeInMSec) / 1000;
}
uint64_t RunningTiming::GetElapsedTimeInMSec() {
uint64_t stopTimeInMsec = GetCurTimeInMSec();
return stopTimeInMsec - mStartTimeInMSec;
}
實現思路
- 構造即初始化
RunningTiming類在構造時即自動記錄起始時間,無需額外調用初始化接口,減少使用步驟,提升易用性。 - 按需提供精度接口
根據實際需求,封裝兩個獲取時間間隔的接口:秒級和毫秒級,便于不同場景下直接使用合適精度。 - 統(tǒng)計代碼執(zhí)行時長
計時范圍是從RunningTiming對象定義開始,到調用GetElapsedTimexxx為止的時間跨度,用于統(tǒng)計該時間段內代碼的執(zhí)行耗時。
實例使用
? 因為對外接口單一,因此使用起來很方便
{
RunningTiming timer;
usleep(100 * 1000); // 休眠 100 毫秒
uint64_t elapsedTime = timer.GetElapsedTimeInMSec();
}
總結
在 C++ 開發(fā)中,直接調用原生接口實現工具類功能雖可行,但往往不夠簡潔,使用成本高。對于這類問題,應通過封裝優(yōu)化,提升易用性和可維護性。
RAII設計理念非常適合封裝獨立、無外部依賴的工具類。它能將資源生命周期與對象生命周期綁定,自動管理資源。但需注意:RAII的前提是初始化必須成功,若存在外部依賴或失敗可能,則不適合使用。