三大計時 API 對比總覽
| API | 頭文件/庫 | 精度 | 適用場景 | 缺點 |
GetTickCount() | <windows.h> | ~15.6 ms (系統時鐘中斷周期) | 粗略耗時統計、超時判斷 | 精度低、49.7 天溢出(GetTickCount64 解決) |
timeGetTime() | <mmsystem.h> + winmm.lib | ~1 ms (可通過 timeBeginPeriod 提升) | 多媒體定時、遊戲循環 | 需鏈接 winmm.lib、全局影響系統調度精度 |
QueryPerformanceCounter() | <windows.h> (Kernel32.lib) | ~0.1 - 1 微秒 (CPU 時鐘頻率) | 高精度性能分析、基準測試、遊戲引擎 | 跨 CPU 核心同步問題(現代 CPU 已修復)、需查詢頻率 |
clock() | <time.h> | ~1 ms (C 標準庫實現,通常基於 GetTickCount 或 QPC) | 跨平台 CPU 時間統計 | 測量 CPU 時間而非牆鐘時間、多線程下為所有線程 CPU 時間之和 |
代碼實現範例
1. GetTickCount / GetTickCount64(推薦 64 位版)
#include <windows.h>
DWORD start = GetTickCount();
// 或 ULONGLONG start = GetTickCount64(); // 避免 49.7 天溢出
FunctionUnderTest();
DWORD elapsed = GetTickCount() - start; // 單位:毫秒
printf("Elapsed: %lu ms\n", elapsed);
2. timeGetTime(需 #pragma comment(lib, "winmm.lib"))
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
// 可選:提升系統定時器精度至 1ms (影響全系統功耗)
TIMECAPS tc; timeGetDevCaps(&tc, sizeof(tc));
timeBeginPeriod(tc.wPeriodMin); // 最小周期
DWORD start = timeGetTime();
FunctionUnderTest();
DWORD elapsed = timeGetTime() - start;
timeEndPeriod(tc.wPeriodMin); // 恢復
3. QueryPerformanceCounter(高精度黃金標準)
#include <windows.h>
LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq); // 僅需查詢一次,全程緩存
QueryPerformanceCounter(&start);
FunctionUnderTest();
QueryPerformanceCounter(&end);
double elapsed_ms = (double)(end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;
printf("Elapsed: %.3f ms\n", elapsed_ms);
4. 封裝為 C++ RAII 計時器類(推薦生產代碼風格)
class ScopedTimer {
LARGE_INTEGER freq_, start_;
const char* name_;
public:
ScopedTimer(const char* name) : name_(name) {
QueryPerformanceFrequency(&freq_);
QueryPerformanceCounter(&start_);
}
~ScopedTimer() {
LARGE_INTEGER end; QueryPerformanceCounter(&end);
double ms = (double)(end.QuadPart - start_.QuadPart) * 1000.0 / freq_.QuadPart;
printf("[TIMER] %s: %.3f ms\n", name_, ms);
}
};
// 用法:
void TestFunction() {
ScopedTimer timer("TestFunction");
// ... 待測代碼 ...
}
// 函數退出時自動打印耗時
進階避坑指南
- CPU 變頻影響:現代 CPU 支持 Invariant TSC,
QueryPerformanceFrequency 返回固定頻率,不受變頻影響(Win10+ / 近代硬體)。舊系統需檢查 QueryPerformanceFrequency 是否穩定。
- 多核同步:早期多核系統 TSC 不同步導致跨核測量錯誤。現代 OS (Win7+) 已在 HAL 層修正,QPC 可安全跨核使用。
- 內聯汇編 RDTSC:極致性能可直接讀取時間戳計數器,但需處理核心遷移、變頻、指令重排,極易出錯,**強烈建議使用 QPC**。
- 編譯器優化干擾:被測代碼若無副作用可能被優化掉。使用
volatile 變量接收結果、或調用外部函數、或內嵌汇編 asm volatile("" ::: "memory") 防止優化。
總結選型建議
- 微秒級精度、性能分析、基準測試:QueryPerformanceCounter 唯一首選。
- 毫秒級、簡單超時、跨平台:GetTickCount64(Win)/
clock_gettime(CLOCK_MONOTONIC)(Linux)。
- 多媒體/遊戲固定幀率循環:timeGetTime +
timeBeginPeriod(1)。
- C 標準庫風格、測量 CPU 時間:clock()。