C++ Boost Chrono实现计时码表流程详解
无水先生 人气:0一、Boost.Chrono说明
库 Boost.Chrono 提供了多种时钟。例如,您可以获取当前时间,也可以测量流程中经过的时间。
Boost.Chrono 的部分内容已添加到 C++11。如果您的开发环境支持 C++11,您可以访问头文件 chrono.xml 中定义的多个时钟。但是,C++11 不支持某些功能,例如用于测量 CPU 时间的时钟。此外,只有 Boost.Chrono 支持用户定义的时间输出格式。
二、示例代码
您可以通过头文件 boost/chrono.hpp 访问所有 Boost.Chrono 时钟。唯一的扩展是用户定义的格式,它需要头文件 boost/chrono_io.hpp。
例 37.1。来自 Boost.Chrono 的所有时钟
#include <boost/chrono.hpp> #include <iostream> using namespace boost::chrono; int main() { std::cout << system_clock::now() << '\n'; #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY std::cout << steady_clock::now() << '\n'; #endif std::cout << high_resolution_clock::now() << '\n'; #ifdef BOOST_CHRONO_HAS_PROCESS_CLOCKS std::cout << process_real_cpu_clock::now() << '\n'; std::cout << process_user_cpu_clock::now() << '\n'; std::cout << process_system_cpu_clock::now() << '\n'; std::cout << process_cpu_clock::now() << '\n'; #endif #ifdef BOOST_CHRONO_HAS_THREAD_CLOCK std::cout << thread_clock::now() << '\n'; #endif }
例 37.1 介绍了 Boost.Chrono 提供的所有时钟。所有时钟都有一个共同的成员函数 now(),它返回一个时间点。所有时间点都相对于普遍有效的时间点。这个参考时间点称为纪 元。一个经常使用的纪 元是 1970 年 1 月 1 日。示例 37.1 为显示的每个时间点写入纪 元。
Boost.Chrono 包括以下时钟:
boost::chrono::system_clock 返回系统时间。这是通常显示在计算机桌面上的时间。如果您更改计算机上的时间,boost::chrono::system_clock 会返回新时间。示例 37.1 将字符串写入标准输出,如下所示:自 1970 年 1 月 1 日以来的 13919594042183544 [1/10000000] 秒。
对于 boost::chrono::system_clock,epoch 没有标准化。这些示例中使用的纪 元 1970 年 1 月 1 日取决于实现。但是,如果您特别想获取自 1970 年 1 月 1 日以来的时间,请调用 to_time_t()。 to_time_t() 是一个静态成员函数,它以 std::time_t 形式返回自 1970 年 1 月 1 日以来的当前系统时间秒数。
boost::chrono::steady_clock 是一个时钟,它总是在稍后访问时返回。即使在计算机上设置了时间, boost::chrono::steady_clock 也会返回稍后的时间。这个时间被称为单调时间。
示例 37.1 显示自系统启动以来的纳秒数。该消息如下所示:自启动以来 10594369282958 纳秒。 boost::chrono::steady_clock 测量自上次启动以来经过的时间。但是,自上次启动后开始测量是一个实现细节。参考点可能会随着不同的实现而改变。
并非所有平台都支持 boost::chrono::steady_clock。只有定义了宏 BOOST_CHRONO_HAS_CLOCK_STEADY 时,时钟才可用。
boost::chrono::high_resolution_clock 是 boost::chrono::system_clock 或 boost::chrono::steady_clock 的类型定义,具体取决于哪个时钟更精确地测量时间。因此,输出与 boost::chrono::high_resolution_clock 所基于的时钟的输出相同。
boost::chrono::process_real_cpu_clock 返回进程运行的 CPU 时间。时钟测量程序启动后的时间。示例 37.1 将一个字符串写入标准输出,如下所示:自进程启动以来的 1000000 纳秒。
您也可以使用 ctime 中的 std::clock() 获得这个时间。事实上,目前 boost::chrono::process_real_cpu_clock 的实现是基于 std::clock() 的。
只有定义了宏 BOOST_CHRONO_HAS_PROCESS_CLOCKS 才能使用 boost::chrono::process_real_cpu_clock 时钟和其他测量 CPU 时间的时钟。
boost::chrono::process_user_cpu_clock 返回进程在用户空间中花费的 CPU 时间。用户空间是指与操作系统功能分开运行的代码。在程序调用的操作系统函数中执行代码所花费的时间不计入用户空间时间。
boost::chrono::process_user_cpu_clock 只返回在用户空间运行的时间。如果程序暂停了一段时间,例如通过 Windows Sleep() 函数,则在 Sleep() 中花费的时间不会由 boost::chrono::process_user_cpu_clock 测量。
示例 37.1 将一个字符串写入标准输出,如下所示:自进程启动以来的 15600100 纳秒。
boost::chrono::process_system_cpu_clock 类似于 boost::chrono::process_user_cpu_clock。然而,这个时钟测量在内核空间中花费的时间。 boost::chrono::process_system_cpu_clock 返回进程执行操作系统函数所花费的 CPU 时间。
示例 37.1 将一个字符串写入标准输出,如下所示: 自进程启动后 0 纳秒。因为这个例子没有直接调用操作系统函数并且因为 Boost.Chrono 只使用了几个操作系统函数,所以 boost::chrono::process_system_cpu_clock 可能返回 0。
boost::chrono::process_cpu_clock 返回一个元组,其中包含 boost::chrono::process_real_cpu_clock、boost::chrono::process_user_cpu_clock 和 boost::chrono::process_system_cpu_clock 返回的 CPU 时间。示例 37.1 将字符串写入标准输出,如下所示:{1000000;15600100;0} 自进程启动后的纳秒。
boost::chrono::thread_clock 返回线程使用的时间。 boost::chrono::thread_clock 测量的时间与 CPU 时间相当,除了它是每个线程而不是每个进程。 boost::chrono::thread_clock 返回线程运行的 CPU 时间。它不区分在用户空间和内核空间中花费的时间。
并非所有平台都支持 boost::chrono::thread_clock。如果定义了宏 BOOST_CHRONO_HAS_THREAD_CLOCK,则只能使用 boost::chrono::thread_clock。
Boost.Chrono 提供宏 BOOST_CHRONO_THREAD_CLOCK_IS_STEADY 来检测 boost::chrono::thread_clock 是否像 boost::chrono::steady_clock 一样测量单调时间。
示例 37.1 将字符串写入标准输出,如下所示:自线程启动以来的 15600100 纳秒。
Boost.Chrono 中的所有时钟都依赖于操作系统功能;因此,操作系统决定了返回时间的精确度和可靠性。
例 37.2。使用 Boost.Chrono 增加和减少持续时间
#include <boost/chrono.hpp> #include <iostream> using namespace boost::chrono; int main() { process_real_cpu_clock::time_point p = process_real_cpu_clock::now(); std::cout << p << '\n'; std::cout << p - nanoseconds{1} << '\n'; std::cout << p + milliseconds{1} << '\n'; std::cout << p + seconds{1} << '\n'; std::cout << p + minutes{1} << '\n'; std::cout << p + hours{1} << '\n'; }
now() 为所有时钟返回 boost::chrono::time_point 类型的对象。这种类型与时钟紧密耦合,因为时间点是相对于由时钟定义的参考时间点测量的。 boost::chrono::time_point 是一个模板,它需要时钟的类型作为参数。每种时钟类型都为其专门的 boost::chrono::time_point 提供类型定义。例如,process_real_cpu_clock 的类型定义是 process_real_cpu_clock::time_point。
Boost.Chrono 还提供了类 boost::chrono::duration,它描述了持续时间。因为 boost::chrono::duration 也是一个模板,所以 Boost.Chrono 提供了六个类 boost::chrono::nanoseconds, boost::chrono::milliseconds, boost::chrono::microseconds, boost::chrono::秒、boost::chrono::minutes 和 boost::chrono::hours,它们更易于使用。
Boost.Chrono 重载了几个运算符来处理时间点和持续时间。示例 37.2 从 p 中减去持续时间或将持续时间添加到 p 以获得新的时间点,这些时间点将写入标准输出。
示例 37.2 以纳秒为单位显示所有时间点。 Boost.Chrono 在处理时间点和持续时间时自动使用最小单位,以确保结果尽可能精确。如果您想将时间点与另一个单元一起使用,则必须对其进行投射。
例 37.3。使用 boost::chrono::time_point_cast() 投射时间点
#include <boost/chrono.hpp> #include <iostream> using namespace boost::chrono; int main() { process_real_cpu_clock::time_point p = process_real_cpu_clock::now(); std::cout << p << '\n'; std::cout << time_point_cast<minutes>(p) << '\n'; }
boost::chrono::time_point_cast() 函数的使用类似于强制转换运算符。示例 37.3 使用 boost::chrono::time_point_cast() 将基于纳秒的时间点转换为以分钟为单位的时间点。在这种情况下,您必须使用 boost::chrono::time_point_cast() ,因为时间点不能以不太精确的单位(分钟)表示而不会丢失精度。您不需要 boost::chrono::time_point_cast() 从不太精确的单位转换为更精确的单位。
Boost.Chrono 还为持续时间提供强制转换运算符。
例 37.4。使用 boost::chrono::duration_cast() 投射持续时间
#include <boost/chrono.hpp> #include <iostream> using namespace boost::chrono; int main() { minutes m{1}; seconds s{35}; std::cout << m + s << '\n'; std::cout << duration_cast<minutes>(m + s) << '\n'; }
示例 37.4 使用函数 boost::chrono::duration_cast() 将持续时间从秒转换为分钟。此示例将 1 分钟写入标准输出。
例 37.5。舍入持续时间
#include <boost/chrono.hpp> #include <iostream> using namespace boost::chrono; int main() { std::cout << floor<minutes>(minutes{1} + seconds{45}) << '\n'; std::cout << round<minutes>(minutes{1} + seconds{15}) << '\n'; std::cout << ceil<minutes>(minutes{1} + seconds{15}) << '\n'; }
Boost.Chrono 还提供了在施法时舍入持续时间的功能。 boost::chrono::round() 向上或向下舍入, boost::chrono::floor() 向下舍入, boost::chrono::ceil() 向上舍入。 boost::chrono::floor() 使用 boost::chrono::duration_cast() - 这两个函数之间没有区别。
示例 37.5 将 1 分钟、1 分钟和 2 分钟写入标准输出。
例 37.6。用于用户定义输出的流操纵器
#define BOOST_CHRONO_VERSION 2 #include <boost/chrono.hpp> #include <boost/chrono/chrono_io.hpp> #include <iostream> using namespace boost::chrono; int main() { std::cout << symbol_format << minutes{10} << '\n'; std::cout << time_fmt(boost::chrono::timezone::local, "%H:%M:%S") << system_clock::now() << '\n'; }
Boost.Chrono 提供了各种流操纵器来格式化时间点和持续时间的输出。例如,使用操纵器 boost::chrono::symbol_format(),时间单位被写为符号而不是名称。因此,示例 37.6 显示 10 分钟。
操纵器 boost::chrono::time_fmt() 可用于设置时区和格式字符串。时区必须设置为 boost::chrono::timezone::local 或 boost::chrono::timezone::utc。格式字符串可以使用标志来引用时间点的各种组件。例如,示例 37.6 将一个字符串写入标准输出,如下所示:15:46:44。
除了流操纵器,Boost.Chrono 还为许多不同的定制提供了方面。例如,有一个方面可以以另一种语言输出时间点。
注意
自 Boost 1.52.0 以来有两个版本的输入/输出函数。从 Boost 1.55.0 开始,默认使用较新的版本。如果您使用早于 1.55.0 的版本,则必须定义宏 BOOST_CHRONO_VERSION 并将其设置为 2 才能使示例 37.6 正常工作。
加载全部内容