我正在尝试为我的C++程序创建一个日志文件。我的目标是在程序的两个点放置两个时间戳,并在文件中打印这两个点之间的CPU时间段。我这样做是因为我想知道我的代码的哪些部分最耗时,以便我可以进行改进(因此我可能想要测量几个代码块(。到目前为止,我已经创建了一个函数,当调用该函数时,会将我作为参数传递的字符串打印到文件中:
#define LOGFILE "myprog.log"
void Log (std::string message){
std::ofstream ofs;
ofs.open(LOGFILE, std::ofstream::out | std::ios::app);
ofs << message << std::endl;
ofs.close();
}
但是,我很难弄清楚如何打印 CPU 时间戳。首先,我不知道我应该使用什么时间测量格式(我应该使用计时还是time_t类型?我正在尝试打印一个时间段,因此如果有持续时间的类型会很有帮助(我已经尝试过 chrono::d uration,但它似乎需要 C++11 支持(。其次,如果我知道要使用什么类型,如何将其打印到文件中?有没有办法将该类型转换为字符串?或者我可以将其直接传递给我的函数并以某种方式打印它吗?
在过去的几天里,这让我很困扰,我似乎无法弄清楚,所以任何输入都会非常有帮助。提前感谢!
获取 CPU 时间戳
您需要使用std::chrono::system_clock
来获取此时间戳。请勿使用std::chrono::steady_clock
或std::chrono::high_resolution_clock
,因为它们用于进行高精度计时测量,并且不保证挂钟时间的保真度或准确性。
auto now = std::chrono::system_clock::now();
//now is a time_point object describing the instant it was recorded according to your system clock
以可读格式打印此 CPU 时间戳
在 C++20 中,这是非常微不足道的。
std::string formatted_time = std::format("{0:%F_%T}", now);
ofs << formatted_time << ": " << message << std::endl;
%F
是%Y-%m-%D
的替代品,它将以 ISO 格式输出年-月-日,即2018-10-09
.%T
对于%H:%M:%S
是相同的,它将输出一个时间,即17:55:34.786
有关如何指定这些参数的详细信息,请参阅std::format
和std::formatter
的规范。
截至 2020 年 12 月,还没有主要的编译器支持<format>
库,因此您可以使用fmt
,这是库的独立实现。
C++20 之前
考虑一下霍华德·欣南特(Howard Hinnant(的date
图书馆,其中大部分作为chrono
图书馆的新部分被并入C++20。在该库中找到的format
函数使用与上面建议的 C++20 版本相同的语法,尽管没有与std::format
集成。
记录:
如果 C++20 功能不可用,就像我的情况一样,您可以使用以下内容:
#include <ctime>
#include <iomanip>
#include <iostream>
using namespace std ;
time_t now = time(nullptr) ;
cout << put_time(localtime(&now), "%T") << endl ;
put_time是在 iomanip 库中定义的,请查看 https://en.cppreference.com/w/cpp/io/manip/put_time,time_t和本地时间来自 ctime,https://en.cppreference.com/w/cpp/chrono/c/ctime
我通常使用我的实现来做这样的事情。
#include <chrono>
#include <ctime>
// strftime format
#define LOGGER_PRETTY_TIME_FORMAT "%Y-%m-%d %H:%M:%S"
// printf format
#define LOGGER_PRETTY_MS_FORMAT ".%03d"
// convert current time to milliseconds since unix epoch
template <typename T>
static int to_ms(const std::chrono::time_point<T>& tp)
{
using namespace std::chrono;
auto dur = tp.time_since_epoch();
return static_cast<int>(duration_cast<milliseconds>(dur).count());
}
// format it in two parts: main part with date and time and part with milliseconds
static std::string pretty_time()
{
auto tp = std::chrono::system_clock::now();
std::time_t current_time = std::chrono::system_clock::to_time_t(tp);
// this function use static global pointer. so it is not thread safe solution
std::tm* time_info = std::localtime(¤t_time);
char buffer[128];
int string_size = strftime(
buffer, sizeof(buffer),
LOGGER_PRETTY_TIME_FORMAT,
time_info
);
int ms = to_ms(tp) % 1000;
string_size += std::snprintf(
buffer + string_size, sizeof(buffer) - string_size,
LOGGER_PRETTY_MS_FORMAT, ms
);
return std::string(buffer, buffer + string_size);
}
它以以下格式返回当前时间:2018-09-23 21:58:52.642
。
是的,它需要--std=c++11
或以上。
如果你想要一个更手动的方法,这是我以前用过的
char buffer[MAX_BUFFER_SIZE];
time_t t = time(NULL);
struct tm *lt = localtime(&t);
snprintf(buffer, MAX_BUFFER_SIZE, "%02d/%02d/%02d %02d:%02d:%02d", lt->tm_mon+1, lt->tm_mday, lt->tm_year%100, lt->tm_hour, lt->tm_min, lt->tm_sec);
然后只需将缓冲区(现在包含时间的字符串表示形式(输出到您的文件中。