【C++11】获取日期时间,用于写日志

#问题:请优化下面函数,要求多线程安全,耗时减小

static inline void GetSysTime(s8* pTimeBuf, u32 dwSize, BOOL32 bFileName = FALSE) {
	if (pTimeBuf == NULL) {
		return;
	}
#if defined(_MSC_VER)
	SYSTEMTIME sys = {0}; 
	GetLocalTime( &sys ); 
	sprintf_s(pTimeBuf, dwSize, "%04d-%02d-%02d_%02d:%02d:%02d.%03d", sys.wYear, sys.wMonth, sys.wDay, 
		sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds);
#else
	time_t timer;
	struct tm* ptTm = NULL;
	time(&timer);
	ptTm = localtime(&timer);
	if (!ptTm) {
		return;
	}
	if (bFileName) {// 日志文件名称
		snprintf(pTimeBuf, dwSize, "%04d-%02d-%02d_%02d-%02d-%02d", ptTm->tm_year + 1900, ptTm->tm_mon + 1, 
			ptTm->tm_mday, ptTm->tm_hour, ptTm->tm_min, ptTm->tm_sec);
	} else {// 打印时间
		struct timespec tTimeTick = {0};
		clock_gettime(CLOCK_MONOTONIC, &tTimeTick);
		snprintf(pTimeBuf, dwSize, "%04d-%02d-%02d %02d:%02d:%02d.%03d", 
			ptTm->tm_year + 1900, ptTm->tm_mon + 1, ptTm->tm_mday, 
			ptTm->tm_hour, ptTm->tm_min, ptTm->tm_sec, static_cast<s32>(tTimeTick.tv_nsec/1000));
	}
#endif
	pTimeBuf[dwSize - 1] = '\0';
}

C++11 实现线程安全的高效时间获取函数

下面是一个使用 C++11 标准实现的多线程安全、高效的 GetSysTime 函数版本:

#include <chrono>
#include <ctime>
#include <cstring>
#include <array>

#if defined(_MSC_VER)
#include <Windows.h>
#else
#include <sys/time.h>
#endif

static inline void GetSysTime(char* pTimeBuf, size_t bufSize, bool forFileName = false)
{
    if (pTimeBuf == nullptr || bufSize == 0) {
        return;
    }

    // 获取当前时间点
    const auto now = std::chrono::system_clock::now();
    const auto now_time_t = std::chrono::system_clock::to_time_t(now);
    
    // 线程安全地转换时间
    struct tm tm_info;
#if defined(_MSC_VER)
    localtime_s(&tm_info, &now_time_t);
#else
    localtime_r(&now_time_t, &tm_info);
#endif

    // 计算毫秒部分
    const auto since_epoch = now.time_since_epoch();
    const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch).count() % 1000;

    if (forFileName) {
        // 文件名格式: YYYY-MM-DD_HH-MM-SS
        snprintf(pTimeBuf, bufSize, "%04d-%02d-%02d_%02d-%02d-%02d",
                 tm_info.tm_year + 1900, tm_info.tm_mon + 1, tm_info.tm_mday,
                 tm_info.tm_hour, tm_info.tm_min, tm_info.tm_sec);
    } else {
        // 普通时间格式: YYYY-MM-DD HH:MM:SS.mmm
        snprintf(pTimeBuf, bufSize, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
                 tm_info.tm_year + 1900, tm_info.tm_mon + 1, tm_info.tm_mday,
                 tm_info.tm_hour, tm_info.tm_min, tm_info.tm_sec,
                 static_cast<int>(ms));
    }
    
    // 确保字符串以null结尾
    if (bufSize > 0) {
        pTimeBuf[bufSize - 1] = '\0';
    }
}

// 使用固定大小缓冲区的重载版本
static inline void GetSysTime(std::array<char, 32>& timeBuf, bool forFileName = false)
{
    GetSysTime(timeBuf.data(), timeBuf.size(), forFileName);
}

关键优化点

  1. 线程安全性

    • 使用 localtime_r (Unix-like) 和 localtime_s (Windows) 替代不安全的 localtime
    • 所有时间操作都使用线程安全的 C++11 标准库函数
  2. 性能优化

    • 使用 std::chrono 高效获取时间
    • 减少系统调用次数(相比原代码减少了不必要的调用)
    • 使用更高效的格式化方式
  3. C++11 特性应用

    • 使用 std::chrono 时间库
    • 提供 std::array 重载版本,避免缓冲区溢出风险
    • 使用更现代的 C++ 类型(size_t 替代 u32bool 替代 BOOL32
  4. 代码质量改进

    • 更严格的参数检查
    • 更清晰的变量命名
    • 移除冗余代码
    • 更一致的跨平台实现

使用示例

#include <iostream>

int main() {
    // 使用动态缓冲区
    char timeBuf1[64];
    GetSysTime(timeBuf1, sizeof(timeBuf1), false);
    std::cout << "Current time: " << timeBuf1 << std::endl;

    // 使用固定大小缓冲区
    std::array<char, 32> timeBuf2;
    GetSysTime(timeBuf2, true);
    std::cout << "File name time: " << timeBuf2.data() << std::endl;

    return 0;
}

性能对比

与原实现相比,这个版本有以下性能优势:

  1. 减少系统调用:原 Linux 实现需要调用 time()clock_gettime() 两次,新版本只需一次系统调用
  2. 更高效的时间计算:使用 std::chrono 直接获取毫秒部分,避免额外的计算
  3. 内存访问更优:使用固定大小缓冲区时,编译器可以进行更好的优化

这个实现完全使用 C++11 标准,同时保持了跨平台兼容性,是原函数的一个高效、安全的替代方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值