排查一个卡顿问题,日志里两行时间戳一模一样,实际两次操作隔了三百多毫秒。代码里用的是 time(nullptr),精度只有秒。
C++ 里取时间戳至少有四个入口,选错一个,后面全是坑。
要毫秒就用 chrono,别用 time
auto ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); 一行拿到 Unix 毫秒,跨平台,C++11 起都能用。
time(nullptr) 返回秒,clock() 返回的是 CPU 时间,不是墙钟。这两个混用,算出来的耗时能差出几倍。
要微秒就把 duration_cast 换成 microseconds,纳秒同理。别自己乘 1000,溢出问题就是这么来的。
计时用 steady_clock
测函数耗时,用 steady_clock 首尾相减。system_clock 会被 NTP 校时往回拨,正好在计时区间里拨一次,结果就是负数。
存数据库、传接口用 system_clock,因为要的是绝对时间;测性能用 steady_clock,因为要的是单调递增。
high_resolution_clock 听着最好,实际在不同标准库实现里可能是前两者的别名,语义不确定,别用它。
Windows 上的两个细节
GetSystemTimeAsFileTime 的精度受系统时钟中断影响,默认 15.6 毫秒左右,拿它算毫秒级耗时不准。要更细用 QueryPerformanceCounter。
格式化输出时区要写清楚:localtime_s 拿本地时间,gmtime_s 拿 UTC。服务器跑在 UTC、日志按本地时间打,对着日志查问题会错八小时。
存成什么类型
毫秒时间戳到 2038 年也没事,前提是用 64 位整数。int 存秒级都撑不到 2038,更别说毫秒。用 int64_t 或者 long long,别图省事用 int。
如果只是相对时间,比如缓存过期,存 steady_clock 的 tick 就行,别转成日期字符串再解析回来,纯属浪费。