如何在C中获得微秒时间戳?
我正在尝试:
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_usec;
Run Code Online (Sandbox Code Playgroud)
但是这会返回一些无意义的值,如果我得到两个时间戳,第二个可以比第一个更小或更大(第二个应该总是更大).是否可以将gettimeofday返回的魔术整数转换为可以实际使用的正常数字?
unw*_*ind 49
您还需要在几秒钟内添加:
unsigned long time_in_micros = 1000000 * tv.tv_sec + tv.tv_usec;
Run Code Online (Sandbox Code Playgroud)
请注意,这将仅持续约2 32 /10 6 =〜4295秒,或虽然大致71分钟(典型的32位系统).
Rob*_*obᵩ 18
获得微秒时间戳有两种选择.第一个(也是最好的)选择是timeval直接使用类型:
struct timeval GetTimeStamp() {
struct timeval tv;
gettimeofday(&tv,NULL);
return tv;
}
Run Code Online (Sandbox Code Playgroud)
第二个,对我来说不太可取的选择是建立一个uint64_t timeval:
uint64_t GetTimeStamp() {
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec*(uint64_t)1000000+tv.tv_usec;
}
Run Code Online (Sandbox Code Playgroud)
Gab*_*les 15
\n\n在 C 中获取以微秒为单位的时间戳?
\n
以下是与该问题标题相关的通用答案:
\nmillis(),micros(), 和nanos()快速总结:如果您很着急并使用 Linux 或 POSIX 系统,请直接跳到下面标题为“ millis()、 ”micros()和“的部分nanos(),然后使用这些函数。如果您不在Linux 或 POSIX 系统上使用 C11 ,则需要将clock_gettime()这些函数替换为timespec_get().
C11: timespec_get()是C11或更高版本标准的一部分,但不允许选择要使用的时钟类型。它也适用于 C++17。请参阅此处的文档std::timespec_get()。但是,对于 C++11 及更高版本,我更喜欢使用不同的方法,可以指定时钟的分辨率和类型,正如我在此处的答案中演示的那样: Getting an Accuracyexecution Time in C++ (micro Second)。
C11timespec_get()解决方案比 C++ 解决方案有更多限制,因为您无法指定时钟分辨率或单调性(“单调”时钟被定义为仅向前计数且永远不能向后或跳跃的时钟 - 例如:时间修正)。测量时间差时,需要单调时钟以确保您永远不会将时钟校正跳跃算作“测量”时间的一部分。
timespec_get()因此,由于我们无法指定要使用的时钟,因此返回的时间戳值的分辨率可能取决于您的硬件体系结构、操作系统和编译器。通过快速连续进行 1000 次左右的测量,然后找到任意两次后续测量之间的最小差异,可以获得该函数分辨率的近似值。您的时钟的实际分辨率保证等于或小于该最小差异。
我在适用于 Linux 的timinglib.cget_estimated_resolution()计时库的函数中演示了这一点。
Linux 和 POSIX: 甚至比timespec_get()C更好的是Linux 和 POSIX 函数clock_gettime()function,它在 Linux 或 POSIX 系统上的 C++ 中也能正常工作。clock_gettime() 确实允许您选择所需的时钟。您可以使用 读取指定的时钟分辨率clock_getres(),尽管这也不能为您提供硬件的真实时钟分辨率。相反,它为您提供 的tv_nsec成员的单位struct timespec。使用get_estimated_resolution()上面和我的timinglib.c /.h 文件中描述的函数来获取分辨率的估计值。
因此,如果您在 Linux 或 POSIX 系统上使用 C,我强烈建议您使用clock_gettime()over timespec_get().
timespec_get()(好的)和 Linux/POSIX clock_gettime()(更好):以下是这两个功能的使用方法:
\ntimespec_get()\n#include <stdint.h> // `UINT64_MAX`\n#include <stdio.h> // `printf()`\n#include <time.h> // `timespec_get()`\n\n/// Convert seconds to nanoseconds\n#define SEC_TO_NS(sec) ((sec)*1000000000)\n\nuint64_t nanoseconds;\nstruct timespec ts;\nint return_code = timespec_get(&ts, TIME_UTC);\nif (return_code == 0)\n{\n printf("Failed to obtain timestamp.\\n");\n nanoseconds = UINT64_MAX; // use this to indicate error\n}\nelse\n{\n // `ts` now contains your timestamp in seconds and nanoseconds! To \n // convert the whole struct to nanoseconds, do this:\n nanoseconds = SEC_TO_NS((uint64_t)ts.tv_sec) + (uint64_t)ts.tv_nsec;\n}\nRun Code Online (Sandbox Code Playgroud)\nclock_gettime()尽可能使用这个!\nCLOCK_MONOTONIC_RAW时钟,它最适合获取用于为系统上的事件计时的时间戳。CLOCK_REALTIME、CLOCK_MONOTONIC、CLOCK_MONOTONIC_RAW等: https: //man7.org/linux/man-pages/man3/clock_gettime.3.htmlCLOCK_REALTIME. 不过,请不要混淆!“实时”并不意味着它是用于“实时”操作系统或精确计时的好时钟。相反,它意味着它是一个时钟,如果时钟漂移,它将定期调整到“实时”或实际的“世界时间”。再次强调,请勿将此时钟用于精确计时,因为系统可以随时向前或向后调整它,而不受您的控制。// This line **must** come **before** including <time.h> in order to\n// bring in the POSIX functions such as `clock_gettime() from <time.h>`!\n#define _POSIX_C_SOURCE 199309L\n\n#include <errno.h> // `errno`\n#include <stdint.h> // `UINT64_MAX`\n#include <stdio.h> // `printf()`\n#include <string.h> // `strerror(errno)`\n#include <time.h> // `clock_gettime()` and `timespec_get()`\n\n/// Convert seconds to nanoseconds\n#define SEC_TO_NS(sec) ((sec)*1000000000)\n\nuint64_t nanoseconds;\nstruct timespec ts;\nint return_code = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);\nif (return_code == -1)\n{\n printf("Failed to obtain timestamp. errno = %i: %s\\n", errno, \n strerror(errno));\n nanoseconds = UINT64_MAX; // use this to indicate error\n}\nelse\n{\n // `ts` now contains your timestamp in seconds and nanoseconds! To \n // convert the whole struct to nanoseconds, do this:\n nanoseconds = SEC_TO_NS((uint64_t)ts.tv_sec) + (uint64_t)ts.tv_nsec;\n}\nRun Code Online (Sandbox Code Playgroud)\nmillis(),micros(), 和nanos():不管怎样,这里是我在 C 中使用的millis()、micros()、 和函数,用于简单的时间戳和代码速度分析。nanos()
我正在使用下面的 Linux/POSIXclock_gettime()函数。如果您在不可用的系统上使用 C11 或更高版本,只需将下面clock_gettime()的所有用法替换为即可。clock_gettime(CLOCK_MONOTONIC_RAW, &ts)timespec_get(&ts, TIME_UTC)
从我的eRCaGuy_hello_world存储库获取最新版本的代码:
\n\n// This line **must** come **before** including <time.h> in order to\n// bring in the POSIX functions such as `clock_gettime() from <time.h>`!\n#define _POSIX_C_SOURCE 199309L\n \n#include <time.h>\n\n/// Convert seconds to milliseconds\n#define SEC_TO_MS(sec) ((sec)*1000)\n/// Convert seconds to microseconds\n#define SEC_TO_US(sec) ((sec)*1000000)\n/// Convert seconds to nanoseconds\n#define SEC_TO_NS(sec) ((sec)*1000000000)\n\n/// Convert nanoseconds to seconds\n#define NS_TO_SEC(ns) ((ns)/1000000000)\n/// Convert nanoseconds to milliseconds\n#define NS_TO_MS(ns) ((ns)/1000000)\n/// Convert nanoseconds to microseconds\n#define NS_TO_US(ns) ((ns)/1000)\n\n/// Get a time stamp in milliseconds.\nuint64_t millis()\n{\n struct timespec ts;\n clock_gettime(CLOCK_MONOTONIC_RAW, &ts);\n uint64_t ms = SEC_TO_MS((uint64_t)ts.tv_sec) + NS_TO_MS((uint64_t)ts.tv_nsec);\n return ms;\n}\n\n/// Get a time stamp in microseconds.\nuint64_t micros()\n{\n struct timespec ts;\n clock_gettime(CLOCK_MONOTONIC_RAW, &ts);\n uint64_t us = SEC_TO_US((uint64_t)ts.tv_sec) + NS_TO_US((uint64_t)ts.tv_nsec);\n return us;\n}\n\n/// Get a time stamp in nanoseconds.\nuint64_t nanos()\n{\n struct timespec ts;\n clock_gettime(CLOCK_MONOTONIC_RAW, &ts);\n uint64_t ns = SEC_TO_NS((uint64_t)ts.tv_sec) + (uint64_t)ts.tv_nsec;\n return ns;\n}\n\n// NB: for all 3 timestamp functions above: gcc defines the type of the internal\n// `tv_sec` seconds value inside the `struct timespec`, which is used\n// internally in these functions, as a signed `long int`. For architectures\n// where `long int` is 64 bits, that means it will have undefined\n// (signed) overflow in 2^64 sec = 5.8455 x 10^11 years. For architectures\n// where this type is 32 bits, it will occur in 2^32 sec = 136 years. If the\n// implementation-defined epoch for the timespec is 1970, then your program\n// could have undefined behavior signed time rollover in as little as\n// 136 years - (year 2021 - year 1970) = 136 - 51 = 85 years. If the epoch\n// was 1900 then it could be as short as 136 - (2021 - 1900) = 136 - 121 =\n// 15 years. Hopefully your program won\'t need to run that long. :). To see,\n// by inspection, what your system\'s epoch is, simply print out a timestamp and\n// calculate how far back a timestamp of 0 would have occurred. Ex: convert\n// the timestamp to years and subtract that number of years from the present\n// year.\nRun Code Online (Sandbox Code Playgroud)\n在我的带有 gcc 编译器的 x86-64 Linux Ubuntu 18.04 系统上,clock_getres()返回分辨率为1 ns。
对于 和clock_gettime(),timespec_get()我还进行了实证测试,我尽可能快地快速获取 1000 个时间戳(请参阅get_estimated_resolution()我的Timinglib.c计时库的函数),并查看时间戳样本之间的最小间隙是多少。这表明我的系统上使用和 时的范围为~14~26 ns,使用 时为~75~130 ns。这可以被认为是这些函数的粗略“实际解决方案”。请参阅 中的测试代码,并查看 中 my和函数(由该测试代码使用)的定义。timespec_get(&ts, TIME_UTC)clock_gettime(CLOCK_MONOTONIC, &ts)clock_gettime(CLOCK_MONOTONIC_RAW, &ts)timinglib_get_resolution.cget_estimated_resolution()get_specified_resolution()timinglib.c
这些结果是特定于硬件的,并且您的硬件上的结果可能会有所不同。
\nusleep()和nanosleep()- 它提醒我我需要做#define _POSIX_C_SOURCE 199309L才能引入clock_gettime()POSIX 函数<time.h>!\n\n\n
_POSIX_C_SOURCE >= 199309L
CLOCK_REALTIME、CLOCK_MONOTONIC、CLOCK_MONOTONIC_RAW等。clock_gettime():https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.htmlclock_gettime()在 Linux 上: https: //linux.die.net/man/3/clock_gettime \ntimespec_get(),就像我上面所做的那样,而不是 POSIX clock_gettime()。https://en.cppreference.com/w/c/chrono/clock说:\n\n\n在 C11 中使用 timespec_get
\n
clock_gettime()选择所需的时钟 ID !另请参阅此处: ***** https://people.cs.rutgers.edu/~pxk/416/notes/c-tutorials/gettime.htmltimespec_getres()使用 POSIXclock_gettime()和函数的示例。clock_getres()我想确切地知道在给定系统上我期望的时钟分辨率有多好。是 ms 分辨率、us 分辨率、ns 分辨率还是其他分辨率?如需参考,请参阅:\nclock_getres()返回1 ns,但实际分辨率约为14~27 ns,根据我的get_estimated_resolution()函数: https: //github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/c/timinglib.c。在此处查看结果:\nSCHED_RR软实时循环调度程序,以获得最佳且最一致的计时。请参阅我的答案clock_nanosleep():如何配置 Linux SCHED_RR 软实时循环调度程序,以便clock_nanosleep()可以将分辨率从约 55 us 提高到约 4 us。struct timeval包含两个组件,第二个和微秒.具有微秒精度的时间戳表示为自tv_sec字段中存储的纪元以及tv_usec中的小数微秒以来的秒数.因此,你不能只是忽略tv_sec并期待合理的结果.
如果使用Linux或*BSD,则可以使用timersub()减去两个struct timeval值,这可能是您想要的.
timespec_get 来自 C11
以最高纳秒的精度返回,四舍五入到实现的分辨率。
#include <time.h>
struct timespec ts;
timespec_get(&ts, TIME_UTC);
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
Run Code Online (Sandbox Code Playgroud)
更多细节在这里:https : //stackoverflow.com/a/36095407/895245
| 归档时间: |
|
| 查看次数: |
119934 次 |
| 最近记录: |