C語言程序性能計時:從 clock() 到納秒級精度
基礎方法:clock() (C 標準庫)
#include <time.h>
#include <stdio.h>
int main() {
clock_t start = clock();
// 待測代碼
for (volatile long i = 0; i < 100000000; ++i);
clock_t end = clock();
double cpu_time_ms = (double)(end - start) * 1000.0 / CLOCKS_PER_SEC;
printf("CPU 時間: %.3f ms\n", cpu_time_ms);
return 0;
}
- 返回進程佔用 CPU 時間(用戶態+內核態),非牆鐘時間。
- 精度受限於
CLOCKS_PER_SEC(通常 1,000,000),理論微秒級,實際常毫秒級。
- 多線程程序返回所有線程 CPU 時間總和。
高精度牆鐘時間:clock_gettime() (POSIX / Linux / macOS / Windows 10+)
#include <time.h>
#include <stdio.h>
#include <inttypes.h> // PRIu64
int main() {
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start); // 单调时钟,不受系统时间调整影响
// 待測代碼
for (volatile long i = 0; i < 100000000; ++i);
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t elapsed_ns = (uint64_t)(end.tv_sec - start.tv_sec) * 1000000000ULL
+ (end.tv_nsec - start.tv_nsec);
printf("牆鐘時間: %" PRIu64 " ns (%.3f ms)\n", elapsed_ns, elapsed_ns / 1e6);
return 0;
}
CLOCK_MONOTONIC:單調遞增,適合測量間隔,不受 NTP/用戶改時間影響。
CLOCK_REALTIME:系統實時時間(牆鐘),可能跳變。
- 納秒級精度,現代硬體可達亞微秒。
Windows 專用高精度:QueryPerformanceCounter
#include <windows.h>
#include <stdio.h>
int main() {
LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
// 待測代碼
for (volatile long i = 0; i < 100000000; ++i);
QueryPerformanceCounter(&end);
double elapsed_ms = (double)(end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;
printf("高精度時間: %.3f ms\n", elapsed_ms);
return 0;
}
跨平台封裝建議
// timer.h
#pragma once
#ifdef _WIN32
#include <windows.h>
typedef LARGE_INTEGER TimerCount;
void timer_start(TimerCount *t);
double timer_elapsed_ms(TimerCount *start);
#else
#include <time.h>
typedef struct timespec TimerCount;
void timer_start(TimerCount *t);
double timer_elapsed_ms(TimerCount *start);
#endif
選型指南
| 需求 | 推薦 API | 精度 | 可移植性 |
| 簡單 CPU 時間統計 | clock() | ~ms | 全平台 (C89) |
| 高精度牆鐘時間 (Linux/macOS/Win10+) | clock_gettime(CLOCK_MONOTONIC) | ns | POSIX + Win10+ |
| Windows 獨立高精度 | QueryPerformanceCounter | ns | 僅 Windows |
| C++11 現代寫法 | std::chrono::high_resolution_clock | ns | 全平台 (C++11) |
注意事項
- 微基測試需預熱(先跑幾輪)、多次取中位數、防止編譯器優化掉代碼(用
volatile 或輸出結果)。
clock() 測量的是 CPU 時間,多核並行程序可能 > 牆鐘時間。
- 嵌入式裸機:讀取 SysTick / DWT_CYCCNT (Cortex-M) / TSC (x86) 寄存器。