繁忙循环中的C ++ 11 chrono high_resolution_clock稳定性?

时间:2018-04-22 19:47:37

标签: c++11 chrono

以下代码利用C ++ 11 std::chrono累积两个后续刻度之间的增量时间,并输出每秒间隔累计的刻度数和此1秒间隔内的平均刻度时间。

然而,在我的Xcode环境下,当我运行代码时(在Debug中),输出似乎远远超过1秒(可能相隔至少2秒) - 似乎时间线延长的时间比实际的时间线。

如果取消注释睡眠线,则代码表现出正确的行为。

谁能告诉我出了什么问题?

#include <iostream>
#include <chrono>
#include <thread>

std::chrono::high_resolution_clock::time_point then{};

double accumulator = 0.0;
size_t count = 0;

void Tick()
{
    if (then != std::chrono::high_resolution_clock::time_point{}) {
        auto delta = std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - then).count();
        accumulator += delta;
        ++count;
        if (accumulator >= 1.0) {
            std::cout << "count: " << count << " | average delta: " << 1.0 / count << std::endl;
            accumulator = 0.0;
            count = 0;
        }
    } else {
        std::cout << "###" << std::endl;
    }
    then = std::chrono::high_resolution_clock::now();
}

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    while (true) {
        Tick();

        // uncomment the following line exhibits the correct behavior
        //std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    return 0;
}

1 个答案:

答案 0 :(得分:0)

因此,经过一些挖掘后,发现delta计算逻辑与now如何被使用是有缺陷的。几点:

  • now只应在输入Tick函数后进行记录并在整个范围内使用
  • 原始代码基本上只测量整个时间线的子部分为delta,这就是为什么部分delta的累积小于实际经过的时间,因此看起来时间延长超过实际时间线!

工作代码如下所示:

#include <iostream>
#include <chrono>
#include <thread>

std::chrono::high_resolution_clock::time_point then{};

double accumulator = 0.0;
size_t count = 0;

void Tick()
{
    auto now = std::chrono::high_resolution_clock::now(); // the time point of this tick

    if (then != std::chrono::high_resolution_clock::time_point{}) {
        auto delta = std::chrono::duration<double>(now - then).count(); // should use the recorded time point 'now'
        accumulator += delta;
        ++count;
        if (accumulator >= 1.0) {
            std::cout << "count: " << count << " | average delta: " << 1.0 / count << std::endl;
            accumulator = 0.0;
            count = 0;
        }
    } else {
        std::cout << "###" << std::endl;
    }
    then = now; // should use the recorded time point as this tick time
}

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    while (true) {
        Tick();

        // other processing
        //std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    return 0;
}