C++ STL chrono和monotonic_time_get_milliseconds的性能对比

1. 核心区别

  1. monotonic_time_get_milliseconds
    • 通常是一个自定义或平台相关的函数。
    • 如果底层实现依赖于 clock_gettime(CLOCK_MONOTONIC)(Linux/Unix)或类似的 API,其性能会与平台的系统调用开销直接相关。
    • 提供时间戳通常以毫秒为单位,可能会涉及额外的转换(如从纳秒到毫秒)。
  2. std::chrono::steady_clock::now()
    • C++ 标准库的一部分,基于平台的单调时钟实现。
    • 在大多数平台上,std::chrono::steady_clock 通常包装了底层的单调时钟 API:
      • Linux/Unix:clock_gettime(CLOCK_MONOTONIC)
      • Windows:QueryPerformanceCounter
      • macOS:mach_absolute_time
    • 提供的时间单位是 std::chrono::time_point,用户可以选择需要的时间精度。

2. 性能比较

以下是两者性能的主要比较点:

指标 monotonic_time_get_milliseconds std::chrono::steady_clock::now()
调用开销 依赖于实现,通常接近底层API性能 包装底层API,额外开销极小
时间精度 毫秒(可能固定) 可提供纳秒或其他精度
可移植性 可能受限于实现 高,跨平台一致
额外转换开销 可能需从纳秒到毫秒转换 无需手动转换,按需选择单位
典型性能(Linux) 20-60 纳秒(如果基于 clock_gettime 50-100 纳秒(轻微额外开销)

3. 具体比较场景

  1. 低级性能比较
    • 如果 monotonic_time_get_milliseconds 是直接封装了 clock_gettime(CLOCK_MONOTONIC) 或类似的函数,其性能可能稍微优于 std::chrono::steady_clock::now(),因为后者会经过轻量的标准库封装。
    • 对于高频调用场景(如游戏引擎或实时系统),这种微小的开销可能会累积,但差异仍然非常小(一般不超过几十纳秒)。
  2. 灵活性与可用性
    • std::chrono::steady_clock 提供了更多灵活性,支持多种时间精度(纳秒、微秒、毫秒等),同时是标准库的一部分,具备更高的可移植性。
    • 如果只需要毫秒精度,并且性能至关重要,monotonic_time_get_milliseconds 的简单实现可能会更快。
  3. 代码维护与可靠性
    • 使用 std::chrono::steady_clock 可以减少对特定平台 API 的依赖,提高代码的可维护性和跨平台性。
    • 自定义的 monotonic_time_get_milliseconds 可能需要额外考虑平台兼容性和潜在的错误。

4. 实际性能测试

在实践中,性能差异可以通过微基准测试来评估。例如,下面是一个简单的 C++ 性能测试代码:

#include
#include
#include
// Example monotonic_time_get_milliseconds implementation
long long monotonic_time_get_milliseconds() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000LL + ts.tv_nsec / 1000000LL;
}

int main() {
constexpr int iterations = 1000000;

// Test monotonic_time_get_milliseconds
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
volatile auto time = monotonic_time_get_milliseconds();
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << “monotonic_time_get_milliseconds: ”
<< std::chrono::duration_cast(end – start).count()
<< ” microseconds\n”;

// Test std::chrono::steady_clock::now
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
volatile auto time = std::chrono::steady_clock::now();
}
end = std::chrono::high_resolution_clock::now();
std::cout << “std::chrono::steady_clock::now: ”
<< std::chrono::duration_cast(end – start).count()
<< ” microseconds\n”;

return 0;
}

输出:
monotonic_time_get_milliseconds: 21185 microseconds
std::chrono::steady_clock::now: 21424 microseconds


5. 总结

  • 性能
    • 如果 monotonic_time_get_milliseconds 是直接调用底层 API,它的性能可能略高,但差距通常很小。
    • 对于绝大多数应用场景,std::chrono::steady_clock::now() 的额外开销可以忽略。
  • 推荐
    • 如果需要高性能计时,并且代码需跨平台,使用 std::chrono::steady_clock::now() 是更好的选择。
    • 如果只关注毫秒级别性能,且代码限定在特定平台上,monotonic_time_get_milliseconds 可能会有微小优势。

Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注