Mac OS X中的clock_gettime替代


68

通过MacPorts安装必要的库后,在Mac OS X上编写的程序编译时,出现此错误:

似乎clock_gettime在Mac OS X中未实现。是否存在另一种以十亿分之一秒为单位的时间获取时间的方法?不幸的是以微秒单位gettimeofday


1
我的文档说:“所有实现都支持系统范围的实时时钟,该时钟由CLOCK_REALTIME标识。” #include <time.h>
2011年

4
那没有帮助。clock_gettime在Mac OS X中没有实现
桑德兰Azabani

6
我知道。在我的链接器命令行中。我根本没有进入链接阶段。Mac OS X没有clock_gettime,而Linux没有。
Delan Azabani'3

2
我为此写了一个快速包装:gist.github.com/alfwatt/3588c5aa1f7a1ef7a3bb
alfwatt

9
需要注意的是MacOS的塞拉利昂10.12(2016年9月,8的XCode)及更高版本支持clock_gettime()直接-在此指出的答案詹姆斯·沃尔德
乔纳森·莱夫勒

Answers:


32

实际上,在Sierra 10.12之前,似乎没有为macOS实施它。您可能需要查看此博客条目。主要思想在以下代码段中:


4
我不想要单调的时间,我想要自纪元以来的实时时间(以纳秒为单位)。
Delan Azabani'3

3
@Delan,我不明白你为什么要这么做,这对于几年级的计数是毫无用处的。通常,您需要十亿分之一秒的时间来计时一个函数。然后,花一些时间在该博客之前和之后就足够了。但是,您始终可以通过在程序开始时使用gettimeofdaymach_absolute_time进行模拟,然后进行累加。
詹斯·古斯特

10
切勿混淆单调和实时。NTP守护程序更正系统时钟时,实时可能会跳跃。实际上,它们是完全不同的两件事。
mic_e 2012年

2
“博客条目”现在已损坏:(
P Marecki 2012年


128

经过数小时的仔细阅读后,我找到了一种获取当前时间的便捷方法:

或查看以下要点:https//gist.github.com/1087739

希望这可以节省时间。干杯!


3
host_get_clock_service价格昂贵吗?为该进程缓存它会付钱吗?可重用吗?线程安全吗?谢谢-:)
彼得

1
还需要包括:#ifdef __MACH__ #include <mach / clock.h> #include <mach / mach.h> #endif
Nikolay Vyahhi 2012年

3
@NikolayVyahhi是的!我的要旨是。尽管由于找不到它们,所以最好将它们添加到答案中。
jbenet'2

4
也许有人定时以上__MACH__代码?使用独立的微秒计时器(经过良好测试),我得到的印象是,上述代码的两次调用花费了大约25微秒的时间。
P Marecki 2012年

1
有谁知道@peterk问题的答案。在我的测试中,缓存似乎使性能提高了一倍,但是我是否需要针对每个线程进行缓存,还是可以创建一个并在所有线程之间共享?
robbie_c 2014年

35

上面的解决方案都不能回答这个问题。他们要么没有给您绝对的Unix时间,要么它们的精度为1微秒。jbenet最受欢迎的解决方案是速度很慢(〜6000ns),即使返回表明如此,也不会以纳秒为单位。下面是jbenet和Dmitri B建议的2种解决方案的测试,以及我对此的看法。您可以运行代码而无需更改。

第三个解决方案的确以纳秒为单位,并为您提供了相当快的Unix绝对时间(〜90ns)。因此,如果有人觉得它有用-请在这里让我们所有人知道:-)。我将坚持使用Dmitri B(代码中的解决方案#1)中的一种-更好地满足我的需求。

我需要替代clock_gettime()的商业质量来进行pthread_…timed ..调用,并且发现此讨论非常有帮助。多谢你们。


1
就像供参考。在我的系统上mach_absolute_time()info.numer / info.denom每次加号或乘号的调用每次调用大约花费33ns:基准:gist.github.com/aktau/9f52f812200d8d69a5d1 libuv问题:github.com/joyent/libuv/pull/1325
Aktau,

30

8
如果您使用CLOCK_REALTIME或CLOCK_MONOTONIC,则还应定义以下内容:#define CLOCK_REALTIME 0 #define CLOCK_MONOTONIC 0
nat chouf 2013年

5
因为a)精度降低了1000倍(尽管还算不错,因为真正返回的时间的粒度clock_gettime很少(永远不会)是1纳秒),并且b)返回的时间gettimeofday是不同且非单调的。在进行时间服务器同步之后,时间服务可能希望避免时间的小幅突然变化,它可能会狂跳(例如,发生夏时制时),或者甚至可能以稍慢/快(!)的速度运行。

4
不幸的是,一天中的时间并不是单调的时钟。(单调时钟专门用于避免与日时钟相关的所有问题,包括管理员或NTP更改时间,leap秒,时区等。)
Dave Pacheco

21

您需要的所有内容均在《技术问答》 QA1398:《技术问答》 QA1398:马赫绝对时间单位中进行了描述,基本上您想要的功能是mach_absolute_time

这是该页面中示例代码的稍早版本,该示例代码使用Mach调用进行所有操作(当前版本使用AbsoluteToNanosecondsCoreServices中的代码)。在当前的OS X中(例如,在x86_64的Snow Leopard上),绝对时间值实际上以纳秒为单位,因此实际上根本不需要任何转换。因此,如果您擅长并编写可移植的代码,则可以进行转换,但是,如果您只是为自己做一些快速而又肮脏的事情,则无需打扰。

FWIW,mach_absolute_time真的快。


15

请注意,macOS Sierra 10.12现在支持clock_gettime():

它确实提供了纳秒级;但是,分辨率为1000,因此(有效地)限制为微秒:

您将需要XCode 8或更高版本才能使用此功能。编译为使用此功能的代码将无法在Mac OS X版本(10.11或更早版本)上运行。


1
我在macOS 10.12上,但无法编译以上内容;我得到Use of undeclared identifier 'CLOCK_REALTIME'
Necktwi '16

1
奇怪,应该与#include <time.h>一起使用。尝试“ xcode-select --install”更新命令行开发人员工具。
詹姆斯·沃尔德

是的,我的Xcode是v7。下载4GB Xcode8对我来说很痛苦。我对xcode-slect --install
Necktwi '16

@JamesWald:我已在问题下发表评论,指出您的答案。对评论进行投票会提高其可见度(多次投票甚至会更好)。
乔纳森·莱夫勒

2
请注意:如果使用XCode 8(或更高版本)进行构建,但目标版本的OSX早于10.12,则会clock_gettime在编译时找到该符号,但是在10.11或更低版本上运行二进制文件时,您将得到“ dyld:找不到符号:_clock_gettime”,因为编译器生成了一个弱符号。
Anon

9

谢谢你的帖子

我认为您可以添加以下几行

让我知道您获得的延迟和粒度


3
如果您将mach_timebase_info调用缓存起来(最好使用静态变量以使其保持整洁)会更好。mach_timebase_info()是系统调用,在我的计算机上大约需要180ns。与〜22ns相对mach_absolute_time(),后者基本上只是采样rdtsc
阿克套2014年

4

迄今为止,Maristic的最佳答案。让我简化并补充一下。#includeInit()

用于:

这样的计时器的等待时间为65ns +/- 2ns(2GHz CPU)。如果您需要一次执行的“时间演化”,请使用此选项。否则10000,即使使用gettimeofday(),也可以循环使用您的代码时间和配置文件,这是可移植的(POSIX),并且延迟为100ns +/- 0.5ns(尽管只有1us粒度)。


1
您知道转换成倍数对精度的影响吗?AFAIK double的精度只有53位,并且mach_absolute_time可以返回64位范围内的任何内容。只是好奇。
阿克套2014年

3

我用clock_get_time尝试了该版本,并缓存了host_get_clock_service调用。它比gettimeofday慢,每次调用花费几微秒的时间。而且,更糟糕的是,返回值的步长为1000,即仍然是微秒级的粒度。

我建议使用gettimeofday,并将tv_usec乘以1000。


1
返回的时间gettimeofday可能是非单调的。在进行时间服务器同步之后,时间服务可能希望避免时间的小幅突然变化,它可能会狂跳(例如,发生夏时制时),或者甚至可能以稍慢/快(!)的速度运行。

2

基于开源的mach_absolute_time.c,我们可以看到该行extern mach_port_t clock_port;告诉我们已经为单调时间初始化了一个mach端口。可以直接访问此时钟端口,而无需诉诸调用mach_absolute_time然后转换a struct timespec。绕过呼叫mach_absolute_time应该会提高性能。

我使用基于extern和类似线程的代码创建了一个小Github存储库(PosixMachTiming)PosixMachTiming模拟的和。它还模拟绝对单调时间的功能。请尝试一下,看看性能如何比较。也许您可能想创建比较测试或仿真其他POSIX时钟/功能?clock_portclock_gettimeCLOCK_REALTIMECLOCK_MONOTONICclock_nanosleep


1

至少追溯到Mountain Lion之前,mach_absolute_time()返回纳秒而不是绝对时间(这是总线周期数)。

MacBook Pro(2 GHz Core i7)上的以下代码显示,mach_absolute_time()在10次运行中调用时间平均为39 ns(最小35分,最大45分),这基本上是两次调用返回mach_absolute_time()之间的时间,大约1次调用:


2
IIRC,所有Intel硬件都使用纳秒,而无论OS版本如何,所有PowerPC硬件都使用总线周期,但是G5可能使用纳秒,我忘了。
dgatwood

0

我找到了另一个便携式解决方案。

声明一些头文件(甚至在您的源文件中):

并添加功能实现:

别忘了包含<time.h>


0

对于MacOS,您可以在其开发人员页面上找到很好的信息 https://developer.apple.com/library/content/documentation/Darwin/Conceptual/KernelProgramming/services/services.html

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.