【发布时间】:2019-07-18 23:20:58
【问题描述】:
我需要将 FILETIME 值格式化为宽字符串缓冲区,并且配置提供了格式字符串。
我实际上在做什么:
Config 提供格式字符串:
L"{YYYY}-{MM}-{DD} {hh}:{mm}:{ss}.{mmm}"将 FILETIME 转换为系统时间:
SYSTEMTIME stUTC;
FileTimeToSystemTime(&fileTime, &stUTC);
- 用 格式化字符串
fmt::format_to(std::back_inserter(buffer), strFormat,
fmt::arg(L"YYYY", stUTC.wYear),
fmt::arg(L"MM", stUTC.wMonth),
fmt::arg(L"DD", stUTC.wDay),
fmt::arg(L"hh", stUTC.wHour),
fmt::arg(L"mm", stUTC.wMinute),
fmt::arg(L"ss", stUTC.wSecond),
fmt::arg(L"mmm", stUTC.wMilliseconds));
我完全理解服务是要付出代价的 :) 但我的代码调用此语句数百万次,并且性能损失明显存在(超过 6% 的 CPU 使用率)。
欢迎“任何我可以做的改进此代码”。
我看到 {fmt} 有一个 time API support。
不幸的是,它似乎无法格式化时间/日期的毫秒部分,并且需要从FILETIME 到std::time_t 的一些转换工作...
我是否应该忘记“自定义”格式字符串并为FILETIME(或SYSTEMTIME)类型提供自定义格式器?这会显着提升性能吗?
如果您能提供任何指导,我将不胜感激。
【问题讨论】:
-
如果我非常关心性能,我不会使用任何像这样的通用格式化工具。相反,我会考虑将自定义格式字符串处理成一个简单的状态机,其中输入由 SYSTEMTIME 结构中的偏移量驱动,以及所有 2、3 和 4 位零填充无符号值的字符串查找表。另一个针对频繁日志条目的小优化是,如果时间与之前的时间相同,则避免转换时间。
-
如果您的日志记录例程显示在您的性能图表中,您通常会误解图表,或者做错了什么。能发一下代码吗?
-
时间是从文件系统元数据中提取的,以百万计。因此,我无法预测它们的值(并且与当前时间无关)。这不是日志记录例程,而是将文件系统元数据转储到 csv 的工具。不过我喜欢你的状态机想法。
-
我添加了一个答案,其中包含一些关于我将如何处理的更具体的细节。在答案中,我指出它并不是真正的状态机。好吧,我想它在技术上是,但它几乎是有史以来最简单的状态机。希望对您有所帮助。
-
你试过使用 fmt 的 constexpr 格式字符串解析器吗? (按照文档中关于启用无效参数类型的编译时检测的说明启用它)