time(NULL)在Macbook Pro上返回不一致的值

时间:2012-09-28 23:11:04

标签: c++ macos time race-condition

time(NULL)返回什么?鉴于文档,我假设它返回了自纪元以来的秒数,但是,当我运行以下代码时:

#include <iostream>
#include "Time.h"
#include "Math.h"

int main () {

    double curT = 0;
    double curJ = 0;

    time_t curTtimeT = 0;
    double curJtimeT = 0;

    //run indefinitely... use a debugger you can stop :-)
    for (double j = 0; j < 2000000000; j++) {

        //get the current time
        curT = time(NULL);
        curTtimeT = time(NULL);

        //check if current time equals previous time
        if (time(NULL) != curT) {
            //output time and approx. "time" through iteration
            std::cout << "Time match with doubles:\t" << curT << "\tdeltaJ:\t\t\t" << (j - curJ) <<std::endl;
            curT = time(NULL);
            curJ = j;
        }

        if (time(NULL) != curTtimeT) {
            //output time and approx. "time" through iteration
            std::cout << "Time match with time_t:\t\t" << curTtimeT << "\t\tdeltaJtimeT:\t\t" << (j - curJtimeT) <<std::endl;
            curTtimeT = time(NULL);
            curJtimeT = j;
        }

    }
    return 0;
}

我得到以下结果(跳过在运行之间似乎没有模式):

Time match with time_t:     1348873002      deltaJtimeT:        290842
Time match with doubles:    1.34887e+09 deltaJ:         2.41017e+06
Time match with doubles:    1.34887e+09 deltaJ:         1.08409e+06
Time match with doubles:    1.34887e+09 deltaJ:         2.16587e+06
Time match with time_t:     1348873007      deltaJtimeT:        5.36928e+06
Time match with doubles:    1.34887e+09 deltaJ:         1.08696e+06
Time match with time_t:     1348873008      deltaJtimeT:        1.08696e+06
Time match with doubles:    1.34887e+09 deltaJ:         1.08534e+06
Time match with doubles:    1.34887e+09 deltaJ:         3.18296e+06
...
Time match with time_t:     1348873122      deltaJtimeT:        2.16217e+06
Time match with doubles:    1.34887e+09 deltaJ:         6.42553e+06
Time match with doubles:    1.34887e+09 deltaJ:         1.08727e+06
Time match with doubles:    1.34887e+09 deltaJ:         2.14147e+06
Time match with doubles:    1.34887e+09 deltaJ:         1.04733e+06
Time match with time_t:     1348873130      deltaJtimeT:        8.42965e+06

注意:我使用deltaJ输出以数字方式显示在控制台实际输出此循环结果时的明显视觉差异。

显然,这似乎不会一直返回自纪元以来的秒数,因为我会看到double和{{1}的非常接近1行的非常一致的输出} 每秒。相反,我会错过time_t1348873002之间的整个范围 - 这些值似乎都没有通过1348873007找到。这些间隙在此循环的整个运行时间内始终如一。

此外,有时它甚至不会输出一些秒(请参阅time(NULL)1348873122之间的差距。)

我不明白为什么输出不会为每个变量类型显示一个条目,每秒实时。相反,似乎1348873130不一致地返回自纪元以来的秒数,并且实际上跳过了一些值。

我错过了什么?

我在Snow Leopard上的X-Code 3.2.5中的2.4GHz双核Macbook Pro上运行这些测试(也许这个问题特定于我的系统)?

5 个答案:

答案 0 :(得分:1)

请参阅<time.h>time()

time_t time(time_t *res);

time_t的类型通常是有符号整数类型。

由于您使用的是"Time.h",因此您可能会对time()提供不同的定义。

我更喜欢<cstdio>得到整齐排列和格式化的输出(我是C程序员而不是C ++程序员),但代码可以编译为:

#include <ctime>
#include <cstdio>
using namespace std;

int main()
{
    double curT = 0;
    double curJ = 0;

    time_t curTtimeT = 0;
    double curJtimeT = 0;

    //run indefinitely... use a debugger you can stop :-)
    for (double j = 0; j < 2000000000; j++)
    { 
        //get the current time
        curT = time(NULL);
        curTtimeT = time(NULL);

        //check if current time equals previous time
        if (time(NULL) != curT) {
            printf("CurT:      %16.2f;  deltaJ: %16.2f\n", curT, j - curJ);
            curT = time(NULL);
            curJ = j;
        }

        if (time(NULL) != curTtimeT) {
            printf("CurTtimeT: %13lld;     deltaJ: %13lld\n", (long long)curTtimeT, (long long)(j - curJtimeT));
            curTtimeT = time(NULL);
            curJtimeT = j;
        }
    }
    return 0;
}

产生如下输出:

CurT:         1348875805.00;  deltaJ:       1215329.00
CurT:         1348875806.00;  deltaJ:       1403669.00
CurTtimeT:    1348875806;     deltaJ:       2618998
CurTtimeT:    1348875807;     deltaJ:       1395183
CurT:         1348875808.00;  deltaJ:       2815155.00
CurT:         1348875809.00;  deltaJ:       1401716.00
CurTtimeT:    1348875809;     deltaJ:       2821688
CurT:         1348875810.00;  deltaJ:       1410729.00
CurT:         1348875811.00;  deltaJ:       1411382.00
CurTtimeT:    1348875811;     deltaJ:       2822111
CurTtimeT:    1348875812;     deltaJ:       1420231
CurT:         1348875813.00;  deltaJ:       2840762.00
CurTtimeT:    1348875815;     deltaJ:       4242399
CurT:         1348875816.00;  deltaJ:       4231937.00

Cur*值是有意义的; deltaJ值不相关,因为您在循环计数器和时间值之间做了区别。我不确定你期望看到什么。

(MacBook Pro,2.3 GHz Intel Core i7,Mac OS X Lion 10.7.5,GCC 4.6.0 - 我需要在本周早些时候发生灾难后恢复我的更高版本的GCC。)

答案 1 :(得分:1)

  

显然,这似乎并没有始终如一地返回自纪元以来的秒数,而是能够看到doubletime_t的非常接近1行的非常一致的输出每秒。

这不遵循。我认为你打算让你的代码与实际有些不同。

具体来说,我认为你需要改变这个:

    //run indefinitely... use a debugger you can stop :-)
    for (double j = 0; j < 2000000000; j++) {

        //get the current time
        curT = time(NULL);
        curTtimeT = time(NULL);

到此:

    //get the current time
    curT = time(NULL);
    curTtimeT = time(NULL);

    //run indefinitely... use a debugger you can stop :-)
    for (double j = 0; j < 2000000000; j++) {

因为实际上,你有一种竞争条件:你正在测试time的返回值是否在循环的某些部分期间发生变化。显然,这种情况不会100%发生;有时第二个会在循环的一个部分翻转,有时它会在另一个部分翻转。

答案 2 :(得分:1)

我认为你的测试代码有点过于复杂。您的第一列看起来正确,但您没有显示所有数字,因此您没有看到秒计数。使用time_t plus double只会使输出混乱。试试这个 - 它很蹩脚,但它每秒都会显示新的时间。

#include <iostream>
#include "Time.h"

int main () {
    //get the current time
    time_t currtime = time(NULL);

    //run indefinitely... use a debugger you can stop :-)
    for (double j = 0; j < 2000000000; j++) {

        //wait until a second has passed
        while (time(NULL) < currtime + 1) {
        };
        currtime = time(NULL);
        std::cout << "Time: " << currtime << "\n";
    }
    return 0;
}

答案 3 :(得分:0)

您在此假设您的应用程序在没有任何干扰的情况下运行:您的系统是一个先发制人的系统,因此有时操作系统可能会与您的流程相交以处理其他事情:您的“时间跳跃”可能是因为这样(即使我仍然很好奇它是否会放弃你的过程5秒钟,但仍然可能发生... ...

此外,我认为您的代码可能会有所不同,因为在没有您期望的情况下进行了一些优化:我建议您检查编译器的设置并禁用优化以查看是否存在任何差异......

你可能会尝试检查任何溢出,即使这是最不可能的,考虑到你的系统(64位整数应该足够你在这里做的)...

答案 4 :(得分:0)

  

对于double和time_t,我能够看到非常接近1行的非常一致的输出。

这正是不应该期望看到的。你应该期望看到很多明显的随机性,这就是你所看到的。循环的每次迭代都会对time()进行两到六次调用,有时会生成格式化输出,有时不生成。 I / O很昂贵,格式化I / O非常昂贵,系统调用如time():它们也很昂贵。

除了运行您的应用程序之外,您的计算机还在执行许多其他操作。它正在创建需要在屏幕上显示的内容,它正在检查您的计算机是否需要更新,它正在运行一些防病毒程序,它正在更新您未关闭的某些浏览器页面等.CPU不断切换上下文在运行程序和运行那些无数其他活动程序之间。那些系统调用是切换上下文的一个完美的地方(也是一个首选的地方)。

循环的每次迭代中有八个位置,程序正在调用OS开关上下文。看到很多变化并不奇怪。