【问题标题】:clock_gettime() returns bad results (Debian wheezy on VirtualBox)clock_gettime() 返回不好的结果(Debian wheezy on VirtualBox)
【发布时间】:2014-06-26 19:18:14
【问题描述】:

我正在尝试使用 clock_gettime() 来监控经过的时间。但是它会返回不好的结果。

我用以下方法对其进行了测试:

#include <time.h>
#include <iostream>
#include <math.h>

using namespace std;

int main()
{
    // Time vars for calculation.
    int ns;

    // Initial struct.
    timespec tt;

    // Get starting time.
    clock_gettime(CLOCK_MONOTONIC,&tt);
    int ns_start = tt.tv_nsec;
    int s_start = tt.tv_sec;

    // Base for second wrap around.
    int ns_base = 1000e6 - ns_start;

    while(true)
    {
        cin.ignore();

        // Get time.
        clock_gettime(CLOCK_MONOTONIC,&tt);

        // Implement/calculate wrap around.
        if(tt.tv_nsec >= ns_start) ns = tt.tv_nsec - ns_start;
        else ns = tt.tv_nsec + ns_base;

        // Display result.
        cout << "Time Passed:\ts: " << tt.tv_sec-s_start << " ms: " << round(ns/1e6) << endl;
    }

    return 0;
}

当我按住任何键一段时间时,我会得到类似的结果:

Time Passed:    s: 1 ms: 833



Time Passed:    s: 2 ms: 308
Time Passed:    s: 2 ms: 354
Time Passed:    s: 2 ms: 415


Time Passed:    s: 2 ms: 459
Time Passed:    s: 2 ms: 511


Time Passed:    s: 2 ms: 566
Time Passed:    s: 2 ms: 613


Time Passed:    s: 2 ms: 661
Time Passed:    s: 2 ms: 712


Time Passed:    s: 2 ms: 762
Time Passed:    s: 2 ms: 813


Time Passed:    s: 2 ms: 861
Time Passed:    s: 2 ms: 920 // crap starts here


Time Passed:    s: 3 ms: 970
Time Passed:    s: 3 ms: 20


Time Passed:    s: 3 ms: 69
Time Passed:    s: 3 ms: 124


Time Passed:    s: 3 ms: 171
Time Passed:    s: 3 ms: 226


Time Passed:    s: 3 ms: 272
Time Passed:    s: 3 ms: 329


Time Passed:    s: 3 ms: 372
Time Passed:    s: 3 ms: 429


Time Passed:    s: 3 ms: 474
Time Passed:    s: 3 ms: 528


Time Passed:    s: 3 ms: 576
Time Passed:    s: 3 ms: 632


Time Passed:    s: 3 ms: 679
Time Passed:    s: 3 ms: 736


Time Passed:    s: 3 ms: 782
Time Passed:    s: 3 ms: 835


Time Passed:    s: 3 ms: 880
Time Passed:    s: 4 ms: 939


Time Passed:    s: 4 ms: 982
Time Passed:    s: 4 ms: 38


Time Passed:    s: 4 ms: 84
Time Passed:    s: 4 ms: 143


Time Passed:    s: 4 ms: 188
Time Passed:    s: 4 ms: 244


Time Passed:    s: 4 ms: 291
Time Passed:    s: 4 ms: 348


Time Passed:    s: 4 ms: 391
Time Passed:    s: 4 ms: 448


Time Passed:    s: 4 ms: 493
Time Passed:    s: 4 ms: 549


Time Passed:    s: 4 ms: 594
Time Passed:    s: 4 ms: 650

Time Passed:    s: 4 ms: 696

Time Passed:    s: 6 ms: 259

Time Passed:    s: 7 ms: 989

通过查看评论时结果混乱的数字应该很明显。

任何人对这是为什么以及如何解决它有任何想法?

【问题讨论】:

  • 我没有看到这种行为,但 tv_sec 和 nsec 通常很长。分配给 int 时可能会截断?
  • @Duck 该实现对两种类型都使用 4 个字节,因为它是典型的 32 位程序,所以不会发生这种情况。
  • @RedAlert on Debian wheezy(我相信 gcc/g++ 4.7)它被标记为实验性支持:/

标签: c++ linux timer


【解决方案1】:

假设计时器从 1.999 秒开始。在 2.001 秒时,您的代码会说已经过去了 1 秒和 2 毫秒,而实际上它应该是 0 秒和 2 毫秒。这是因为您要从当前秒中减去起始秒,即使纳秒部分还没有通过其起始值。

您对纳秒环绕的想法是正确的。让我们扩展它以防止秒数超过正确值。这是一种方法:

#include <time.h>
#include <iostream>
#include <math.h>

using namespace std;

int main()
{
    // Time vars for calculation.
    int ns;
    int s;

    // Initial struct.
    timespec tt;

    // Get starting time.
    clock_gettime(CLOCK_MONOTONIC,&tt);
    int ns_start = tt.tv_nsec;
    int s_start = tt.tv_sec;

    // Base for second wrap around.
    int ns_base = 1000e6 - ns_start;

    while(true)
    {
        cin.ignore();

        // Get time.
        clock_gettime(CLOCK_MONOTONIC,&tt);

        // Implement/calculate wrap around.
        if(tt.tv_nsec >= ns_start)
        {
            ns = tt.tv_nsec - ns_start;
            s = tt.tv_sec - s_start;
        }
        else
        {
            ns = tt.tv_nsec + ns_base;
            s = tt.tv_sec - s_start - 1;
        }

        // Display result.
        cout << "Time Passed:\ts: " << s << " ms: " << round(ns/1e6) << endl;
    }

    return 0;
}

【讨论】:

  • 你先生,真棒。进来,分析问题,提供最小的(并且与原始代码的偏差最小),清晰明确的解决方案(具有根本原因推理),让其他人看起来像鸭子。这才是真正的专业人士应该有的样子。谢谢你的回答。
猜你喜欢
  • 2014-08-18
  • 1970-01-01
  • 1970-01-01
  • 2014-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多