steady_clock和system_clock之间的区别? [英] Difference between steady_clock vs system_clock?

查看:4687
本文介绍了steady_clock和system_clock之间的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过查看数据的时间戳来查看我的数据是否为120秒,所以我有以下代码:

  uint64_t now = duration_cast< milliseconds>(steady_clock :: now()。time_since_epoch())count(); 
bool is_old =(120 * 1000<(now - data_holder-> getTimestamp()));

在上述代码 data_holder-> getTimestamp()是uint64_t,返回以毫秒为单位的时间戳。



现在当我打印出现在这个 10011360 ,当我打印出 data_holder-> getTimestamp() 1437520382241 所以现在和数据存储器时间戳的差异应该是负的吗?为什么它会如下面的日志中所示的积极的?

  2015-07-21 16:13:02,530 WARN 0x7f35312d1700 data_check -  now value:10011360,data holder timestamp:1437520382241,difference:18446742636199180735 

?从上面的数据持有者的时间戳,它不看上去是120秒的旧数据,所以我觉得在我的代码有问题吗?因为如果我将数据持有者时间戳转换为实际时间(使用epoch转换器),然后将其与日志时间进行比较,如上所示几乎相同。



我使用 steady_clock ,如上所示。我需要在这里使用 system_clock 吗? steady_clock system_clock 之间的区别在于layman术语。

解决方案

以相反的顺序回答问题:


steady_clock vs system_clock 之间有什么区别? b $ b条款。


如果您在您的帐户中持有 system_clock



如果你持有一个 steady_clock 在你的手中,你会叫它一个秒表,它会告诉你一个人跑了一圈,但它不会告诉你什么时候是。



如果你不得不,你可以计时某人用你的手表跑一圈。但如果你的手表(如我的)定期与另一台机器(如博尔德CO的原子钟)谈话,以纠正自己的当前时间,它可能会在时间上轻微的错误。秒表不会犯这样的错误,但它也不能告诉你正确的当前时间是什么。


看起来不错吗?


否。即使它给了你合理的答案,我也不会说这是对的。不要感觉不好,这是很多人用< chrono> 库创建的初学者错误。



< chrono> 库中有一个简单的规则。该规则实际上并不完全正确(因此它是一条指南)。但它足够接近以至于几乎总是遵循的指南:


不要使用 count ()


和一个推论:



< blockquote>

不要使用 time_since_epoch()


< chrono> 库围绕类型安全系统设计,旨在保护您免受单位转换错误的影响。如果您不小心尝试了不安全的转换,则会在编译时捕获错误(而不是运行时错误)。



成员函数 count() time_since_epoch()是这种类型安全系统中的escape hatches...仅用于紧急。当(例如)委员会忽略为< chrono> 提供完成工作所需的所有工具(例如I /



查看您的代码和其他的使用 count()

/ code>和 time_since_epoch(),并仔细检查这些函数的每次使用:是否有任何方式的代码可以重写以消除它们使用?



查看代码的第一行:

  uint64_t now = duration_cast< milliseconds>(steady_clock :: now()。time_since_epoch())。count(); 

现在 time_point (从 steady_clock )。它的单位是毫秒,但在这个时候我不相信单位是重要的。重要的是现在是从 steady_clock检索的 time_point

  auto now = steady_clock :: now 

您的第二行比较复杂:

  bool is_old =(120 * 1000<(now  -  data_holder-> getTimestamp())); 

让我们从 data_holder-> getTimestamp():如果您可以修改 getTimestamp(),您应该修改它以返回 time_point ,而不是 uint64_t 。要这样做,你必须知道正确的单位(你做的事情 - 毫秒),,你必须知道正确的时期。时代是衡量您的毫秒的时间点。



在这种情况下,1437520382241ms大约45.6年。假设这是最近的时间戳,45.6年前非常接近1970-01-01。事实证明, system_clock()的每个实现都使用1970-01-01作为其纪元(虽然每个实现计数与这个纪元不同的单位)。



因此,要么修改 getTimestamp()以返回 time_point ,或用 time_point< system_clock,milliseconds> getTimestamp()的返回包裹起来:

  auto dh_ts = system_clock :: time_point {milliseconds {data_holder-> getTimestamp()}}; 

现在您的第二行是:

  bool is_old =(120 * 1000<(now  -  dh_ts)); 

另一个很好的指南:


如果您在< chrono> 代码中看到转换因子,则会出错。 < chrono> 进行转换。




  bool is_old =(minutes {2}<(now  -  dh_ts)); 

下一步是文体,但现在你的代码很简单,这是吸引你的东西:

  bool is_old = minutes {2}现在 -  dh_ts; 

如果您能够修改 getTimestamp()返回一个类型安全的值,这个代码也可以看起来像:

  bool is_old = minutes {2} now  -  data_holder-> getTimestamp(); 

唉,无论哪种方式,这个错误消息应该沿着在现在和<$之间没有有效的运算符 - () c $ c> dh_ts


这是类型安全系统,错误!


问题是 time_point 不能从 time_point steady_clock 中减去> system_clock 不同时期)。所以你必须切换到:

  auto now = system_clock :: now(); 

将它们放在一起:

  #include< chrono> 
#include< cstdint>
#include< memory>

struct DataHolder
{
std :: chrono :: system_clock :: time_point
getTimestamp()
{
using namespace std ::计时器
return system_clock :: time_point {milliseconds {1437520382241}};
}
};

int
main()
{
using namespace std;
using namespace std :: chrono;
auto data_holder = std :: unique_ptr< DataHolder>(new DataHolder);

auto now = system_clock :: now();
bool is_old = minutes {2}< now - data_holder-> getTimestamp();
}

总结:




  • 拒绝使用 count()(I / O除外)。

  • 拒绝使用 time_since_epoch()(除了I / O)。

  • 拒绝使用转换因子(如1000)


$ b

如果您在上述四点中获得成功,没有遇到任何运行时错误(但你会得到你的公平的编译时间错误的份额)。


I am trying to see whether my data is 120 second old or not by looking at the timestamp of the data so I have below code:

uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));

In the above code data_holder->getTimestamp() is uint64_t which returns timestamp in milliseconds.

Now when I print out now variable value, I see this 10011360 and when I print out data_holder->getTimestamp() value which is 1437520382241 so the difference of now and data holder timestamp should be negative right? Why it is coming as positive as shown in the below logs?

2015-07-21 16:13:02,530 WARN 0x7f35312d1700 data_check - now value: 10011360 , data holder timestamp: 1437520382241 , difference: 18446742636199180735

Does my above code looks right? And from the above data holder timestamp, it doesn't look to be 120 second old data right so I feel something is wrong in my code? Since if I convert that data holder timestamp to actual time (using epoch converter) and then compare it with logs time as shown above it is almost same.

I am using steady_clock as shown above. Do I need to use system_clock here? What is the difference between steady_clock vs system_clock in layman terms. I am running this code on Ubuntu 14.04 box.

解决方案

Answering questions in reverse order:

What is the difference between steady_clock vs system_clock in layman terms.

If you're holding a system_clock in your hand, you would call it a watch, and it would tell you what time it is.

If you're holding a steady_clock in your hand, you would call it a stopwatch, and it would tell you how fast someone ran a lap, but it would not tell you what time it is.

If you had to, you could time someone running a lap with your watch. But if your watch (like mine) periodically talked to another machine (such as the atomic clock in Boulder CO) to correct itself to the current time, it might make minor mistakes in timing that lap. The stopwatch won't make that mistake, but it also can't tell you what the correct current time is.

Does my above code look right?

No. And even if it gave you reasonable answers, I would not say it is right. Don't feel bad, this is a beginner mistake that lots of people make with the <chrono> library.

There is a simple rule I follow with the <chrono> library. The rule is actually not completely correct (thus it is a guideline). But it is close enough to correct to be a guideline that is nearly always followed:

Don't use count().

And a corollary:

Don't use time_since_epoch().

The <chrono> library is designed around a type-safe system meant to protect you from units conversions mistakes. If you accidentally attempt an unsafe conversion, the error is caught at compile time (as opposed to it being a run time error).

The member functions count() and time_since_epoch() are "escape hatches" out of this type-safe system ... to be used only in cases of emergency. Such emergencies arise when (for example) the committee neglects to give you all the tools you need to get the job done (such as I/O) for the <chrono> types, or such as the need to interface with some other timing API via integers.

Review your code and other's for use of count() and time_since_epoch() and scrutinize each use of these functions: Is there any way the code could be rewritten to eliminate their use?

Reviewing the first line of your code:

uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();

now is a time_point (from steady_clock). It units are milliseconds, but at this time I'm not convinced that the units are important. What is important is that now is a time_point retrieved from steady_clock:

auto now = steady_clock::now();

Your second line is more complicated:

bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));

Let's start with data_holder->getTimestamp(): If you can modify getTimestamp(), you should modify it to return a time_point instead of a uint64_t. To do so, you will have to know the correct units (which you do -- milliseconds), and you will have to know the correct epoch. The epoch is the time point against which your milliseconds are measured from.

In this case 1437520382241ms is about 45.6 years. Assuming this is a recent time stamp, 45.6 years ago was very close to 1970-01-01. As it turns out, every implementation of system_clock() uses 1970-01-01 as its epoch (though each implementation counts different units from this epoch).

So either modify getTimestamp() to return a time_point<system_clock, milliseconds>, or wrap the return of getTimestamp() with time_point<system_clock, milliseconds>:

auto dh_ts = system_clock::time_point{milliseconds{data_holder->getTimestamp()}};

Now your second line is down to:

bool is_old = (120 * 1000 < (now - dh_ts));

Another good guideline:

If you see conversion factors in your <chrono> code, you're doing it wrong. <chrono> lives for doing the conversions for you.

bool is_old = (minutes{2} < (now - dh_ts));

This next step is stylistic, but now your code is simple enough to get rid of your excess parentheses if that is something that appeals to you:

bool is_old = minutes{2} < now - dh_ts;

If you were able to modify the getTimestamp() to return a type-safe value this code could also look like:

bool is_old = minutes{2} < now - data_holder->getTimestamp();

Alas, either way, this still does not compile! The error message should state something along the lines that that there is no valid operator-() between now and dh_ts.

This is the type-safety system coming in to save you from run time errors!

The problem is that time_points from system_clock can't be subtracted from time_points from steady_clock (because the two have different epochs). So you have to switch to:

auto now = system_clock::now();

Putting it all together:

#include <chrono>
#include <cstdint>
#include <memory>

struct DataHolder
{
    std::chrono::system_clock::time_point
    getTimestamp()
    {
        using namespace std::chrono;
        return system_clock::time_point{milliseconds{1437520382241}};
    }
};

int
main()
{
    using namespace std;
    using namespace std::chrono;
    auto data_holder = std::unique_ptr<DataHolder>(new DataHolder);

    auto now = system_clock::now();
    bool is_old = minutes{2} < now - data_holder->getTimestamp();
}

In summary:

  • Refuse to use count() (except for I/O).
  • Refuse to use time_since_epoch() (except for I/O).
  • Refuse to use conversion factors (such as 1000).
  • Argue with it until it compiles.

If you succeed in the above four points, you will most likely not experience any run time errors (but you will get your fair share of compile time errors).

这篇关于steady_clock和system_clock之间的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆